diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 33868cf56..c453001b7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -14,6 +14,7 @@ jobs: if: "! github.event.pull_request.draft" runs-on: ubuntu-latest + timeout-minutes: 10 env: RAILS_ENV: test @@ -27,7 +28,8 @@ jobs: POSTGRES_DB: idiario_test ports: - 5432:5432 - options: --health-cmd pg_isready + options: + --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 @@ -40,7 +42,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Setup Ruby and install gems uses: ruby/setup-ruby@v1 @@ -48,8 +50,6 @@ jobs: ruby-version: "2.6.6" bundler: "2.4.22" bundler-cache: true - env: - ImageOS: ubuntu20 - name: Configure database run: cp config/database.sample.yml config/database.yml @@ -67,7 +67,9 @@ jobs: " > config/secrets.yml - name: Migrate - run: RAILS_ENV=test bundle exec rake db:migrate + run: | + RAILS_ENV=test bundle exec rake db:migrate - name: Tests - run: bundle exec rspec --exclude-pattern 'spec/acceptance/*.feature' + run: | + RAILS_ENV=test bundle exec rspec --exclude-pattern 'spec/acceptance/*.feature' diff --git a/app/assets/javascripts/index.js b/app/assets/javascripts/index.js index 7e99995c0..9cf175233 100644 --- a/app/assets/javascripts/index.js +++ b/app/assets/javascripts/index.js @@ -39,6 +39,9 @@ $(function(){ $('.remote .pagination a').on('click', function() { + var onPageChange = new CustomEvent('onPageChange'); + document.dispatchEvent(onPageChange); + $.getScript(this.href); return false; } diff --git a/app/assets/javascripts/views/discipline_teaching_plans/form.js.erb b/app/assets/javascripts/views/discipline_teaching_plans/form.js.erb index 501743906..58bc55c72 100644 --- a/app/assets/javascripts/views/discipline_teaching_plans/form.js.erb +++ b/app/assets/javascripts/views/discipline_teaching_plans/form.js.erb @@ -6,6 +6,7 @@ $(function () { var $unity = $('#discipline_teaching_plan_teaching_plan_attributes_unity_id'); var $grade = $('#discipline_teaching_plan_teaching_plan_attributes_grade_id'); + var $year =$('#discipline_teaching_plan_teaching_plan_attributes_year'); var $discipline = $('#discipline_teaching_plan_discipline_id'); var $schoolTermType = $('#discipline_teaching_plan_teaching_plan_attributes_school_term_type_id'); var $schoolTermContainer = $('#school-term-container'); @@ -16,6 +17,7 @@ $(function () { function fetchDisciplines() { var unity_id = $unity.select2('val'); var grade_id = $grade.select2('val'); + var year = $year.val(); $discipline.select2('val', ''); $discipline.select2({ data: [] }); @@ -25,6 +27,7 @@ $(function () { url: Routes.search_by_grade_and_unity_disciplines_pt_br_path({ by_unity_id: unity_id, by_grade: grade_id, + year: year, format: 'json' }), success: handleFetchDisciplinesSuccess, diff --git a/app/assets/javascripts/views/knowledge_area_content_records/form.js b/app/assets/javascripts/views/knowledge_area_content_records/form.js index 4dc5fc1db..5919055cd 100644 --- a/app/assets/javascripts/views/knowledge_area_content_records/form.js +++ b/app/assets/javascripts/views/knowledge_area_content_records/form.js @@ -1,19 +1,26 @@ -$(function () { - 'use strict'; +$(function() { + "use strict"; // Regular expression for dd/mm/yyyy date including validation for leap year and more - var dateRegex = '^(?:(?:31(\\/)(?:0?[13578]|1[02]))\\1|(?:(?:29|30)(\\/)(?:0?[1,3-9]|1[0-2])\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$|^(?:29(\\/)0?2\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\\d|2[0-8])(\\/)(?:(?:0?[1-9])|(?:1[0-2]))\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$'; + var dateRegex = + "^(?:(?:31(\\/)(?:0?[13578]|1[02]))\\1|(?:(?:29|30)(\\/)(?:0?[1,3-9]|1[0-2])\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$|^(?:29(\\/)0?2\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\\d|2[0-8])(\\/)(?:(?:0?[1-9])|(?:1[0-2]))\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$"; var flashMessages = new FlashMessages(); - var $classroom = $('#knowledge_area_content_record_content_record_attributes_classroom_id'); - var $knowledgeArea = $('#knowledge_area_content_record_knowledge_area_ids'); - var $recordDate = $('#knowledge_area_content_record_content_record_attributes_record_date'); - var $contents = $('#knowledge_area_content_record_content_record_attributes_contents_tags'); + var $classroom = $( + "#knowledge_area_content_record_content_record_attributes_classroom_id" + ); + var $knowledgeArea = $("#knowledge_area_content_record_knowledge_area_ids"); + var $recordDate = $( + "#knowledge_area_content_record_content_record_attributes_record_date" + ); + var $contents = $( + "#knowledge_area_content_record_content_record_attributes_contents_tags" + ); var idContentsCounter = 1; - $classroom.on('change', function(){ - var classroom_id = $classroom.select2('val'); + $classroom.on("change", function() { + var classroom_id = $classroom.select2("val"); - $knowledgeArea.select2('val', ''); + $knowledgeArea.select2("val", ""); $knowledgeArea.select2({ data: [] }); if (!_.isEmpty(classroom_id)) { @@ -22,104 +29,136 @@ $(function () { loadContents(); }); - - var handleFetchContentsSuccess = function(data){ + var handleFetchContentsSuccess = function(data) { if (!_.isEmpty(data.contents)) { _.each(data.contents, function(content) { - if(!$('input[type=checkbox][data-content_description="'+content.description+'"]').length){ - var html = JST['templates/knowledge_area_content_records/contents_list_item'](content); - $('#contents-list').append(html); + if ( + !$( + 'input[type=checkbox][data-content_description="' + + content.description + + '"]' + ).length + ) { + var html = JST[ + "templates/knowledge_area_content_records/contents_list_item" + ](content); + $("#contents-list").append(html); } }); - $('.list-group.checked-list-box .list-group-item:not(.initialized)').each(initializeListEvents); + $(".list-group.checked-list-box .list-group-item:not(.initialized)").each( + initializeListEvents + ); } - } + }; - var handleFetchContentsError = function(){ - flashMessages.error('Ocorreu um erro ao buscar os conteúdos de acordo com filtros informados.'); - } + var handleFetchContentsError = function() { + flashMessages.error( + "Ocorreu um erro ao buscar os conteúdos de acordo com filtros informados." + ); + }; - var fetchContents = function(classroom_id, knowledge_area_ids, date){ + var fetchContents = function(classroom_id, knowledge_area_ids, date) { var params = { classroom_id: classroom_id, knowledge_area_ids: knowledge_area_ids, date: date, fetch_for_knowledge_area_records: true, format: "json" - } + }; $.ajax({ url: Routes.contents_pt_br_path(params), success: handleFetchContentsSuccess, error: handleFetchContentsError }); + }; - } - - var loadContents = function(){ - var classroom_id = $classroom.select2('val'); - var knowledge_area_ids = $knowledgeArea.select2('val'); + var loadContents = function() { + var classroom_id = $classroom.select2("val"); + var knowledge_area_ids = $knowledgeArea.select2("val"); var date = $recordDate.val(); - $('#contents-list .list-group-item:not(.manual)').remove(); + $("#contents-list .list-group-item:not(.manual)").remove(); - if (!_.isEmpty(classroom_id) && - !_.isEmpty(knowledge_area_ids) && - !_.isEmpty(date.match(dateRegex))) { + if ( + !_.isEmpty(classroom_id) && + !_.isEmpty(knowledge_area_ids) && + !_.isEmpty(date.match(dateRegex)) + ) { fetchContents(classroom_id, knowledge_area_ids, date); } - } + }; - $knowledgeArea.on('change', function(){ + $knowledgeArea.on("change", function() { loadContents(); }); - $recordDate.on('change', function(){ + $recordDate.on("change", function() { loadContents(); }); function fetchKnowledgeAreas(classroom_id) { $.ajax({ - url: Routes.knowledge_areas_pt_br_path({ classroom_id: classroom_id, format: 'json' }), + url: Routes.knowledge_areas_pt_br_path({ + classroom_id: classroom_id, + format: "json" + }), success: handlefetchKnowledgeAreasSuccess, error: handlefetchKnowledgeAreasError }); - }; + } function handlefetchKnowledgeAreasSuccess(knowledge_areas) { - var selectedKnowledgeAreas = _.map(knowledge_areas, function(knowledge_area) { - return { id: knowledge_area['id'], text: knowledge_area['description'] }; + var selectedKnowledgeAreas = _.map(knowledge_areas, function( + knowledge_area + ) { + return { id: knowledge_area["id"], text: knowledge_area["description"] }; }); - $knowledgeArea.select2({ data: selectedKnowledgeAreas }); - }; + $knowledgeArea.select2({ data: selectedKnowledgeAreas, multiple: true }); + } function handlefetchKnowledgeAreasError() { - flashMessages.error('Ocorreu um erro ao buscar as áreas de conhecimento da turma selecionada.'); - }; + flashMessages.error( + "Ocorreu um erro ao buscar as áreas de conhecimento da turma selecionada." + ); + } - $contents.on('change', function(e){ - if(e.val.length){ - var uniqueId = 'customId_' + idContentsCounter++; + $contents.on("change", function(e) { + if (e.val.length) { + var uniqueId = "customId_" + idContentsCounter++; var content_description = e.val.join(", "); - if(content_description.trim().length && - !$('input[type=checkbox][data-content_description="'+content_description+'"]').length){ - - var html = JST['templates/layouts/contents_list_manual_item']({ + if ( + content_description.trim().length && + !$( + 'input[type=checkbox][data-content_description="' + + content_description + + '"]' + ).length + ) { + var html = JST["templates/layouts/contents_list_manual_item"]({ id: uniqueId, description: content_description, - model_name: 'knowledge_area_content_record', - submodel_name: 'content_record' + model_name: "knowledge_area_content_record", + submodel_name: "content_record" }); - $('#contents-list').append(html); - $('.list-group.checked-list-box .list-group-item:not(.initialized)').each(initializeListEvents); - }else{ - var content_input = $('input[type=checkbox][data-content_description="'+content_description+'"]'); - content_input.closest('li').show(); - content_input.prop('checked', true).trigger('change'); + $("#contents-list").append(html); + $( + ".list-group.checked-list-box .list-group-item:not(.initialized)" + ).each(initializeListEvents); + } else { + var content_input = $( + 'input[type=checkbox][data-content_description="' + + content_description + + '"]' + ); + content_input.closest("li").show(); + content_input.prop("checked", true).trigger("change"); } - $('.knowledge_area_content_record_content_record_contents_tags .select2-input').val(""); + $( + ".knowledge_area_content_record_content_record_contents_tags .select2-input" + ).val(""); } - $(this).select2('val', ''); + $(this).select2("val", ""); }); }); diff --git a/app/assets/javascripts/views/observation_record_report/form.js b/app/assets/javascripts/views/observation_record_report/form.js index dc8279621..d72cabe13 100644 --- a/app/assets/javascripts/views/observation_record_report/form.js +++ b/app/assets/javascripts/views/observation_record_report/form.js @@ -82,7 +82,9 @@ $(function () { return { id: discipline.table.id, name: discipline.table.name, text: discipline.table.text }; }); - selectedDisciplines.unshift({ id: 'all', name: '', text: 'Todas' }); + if (selectedDisciplines.length > 1) { + selectedDisciplines.unshift({ id: 'all', name: '', text: 'Todas' }); + } $discipline.select2({ data: selectedDisciplines }); } @@ -95,4 +97,13 @@ $(function () { $classroom.val('').select2({ data: [] }); $discipline.val('').select2({ data: [] }); } + + $('form').submit(function () { + var tempoEspera = 2000; + + // Define um timeout para habilitar o botão após o tempo de espera + setTimeout(function () { + $('#btn-submit').prop('disabled', false); + }, tempoEspera); + }); }); diff --git a/app/assets/javascripts/views/users/index.js b/app/assets/javascripts/views/users/index.js index fec6707d9..106a1c9ee 100644 --- a/app/assets/javascripts/views/users/index.js +++ b/app/assets/javascripts/views/users/index.js @@ -1,25 +1,39 @@ $(function() { var selected = []; + $(document).on('click', 'ul.pagination > li > a', function(e) { + var onPageChange = new CustomEvent('onPageChange'); + document.dispatchEvent(onPageChange); + }); + + document.addEventListener("onPageChange", function (e) { + $("#select-all").prop("checked", false) + }) + $('body').on('change', '.selected_users', function(event) { - selected = []; - $('.selected_users:checked').each(function() { - selected.push($(this).attr('value')); - }); + selected = $('#export_selected_selected_users').val().split(","); + + if ($(this).prop('checked')) { + selected.push($(this).attr('value')) + } else { + selected.pop($(this).attr('value')) + } + $('#export_selected_selected_users').val(selected); }); $('body').on('change', '#select-all', function(e) { - selected = []; + selected = $('#export_selected_selected_users').val().split(","); + $('.selected_users:checked').each(function() { - if (!_.contains(selected, $(this).attr('value'))) { + if (!_.includes(selected, $(this).attr('value'))) { selected.push($(this).attr('value')); } $('#export_selected_selected_users').val(selected); }); $('.selected_users').each(function() { - if (!_.contains(selected, $(this).attr('value'))) { + if (!_.includes(selected, $(this).attr('value'))) { selected.pop($(this).attr('value')); } $('#export_selected_selected_users').val(selected); diff --git a/app/controllers/api/v2/list_attendances_by_classroom_controller.rb b/app/controllers/api/v2/list_attendances_by_classroom_controller.rb new file mode 100644 index 000000000..700734fbb --- /dev/null +++ b/app/controllers/api/v2/list_attendances_by_classroom_controller.rb @@ -0,0 +1,29 @@ +module Api + module V2 + class ListAttendancesByClassroomController < Api::V2::BaseController + respond_to :json + + def index + required_params = %i[classrooms start_at end_at year] + missing_params = validate_required_params(required_params) + + return if missing_params + + classrooms_api_code = params[:classrooms] + start_at = params[:start_at] + end_at = params[:end_at] + year = params[:year] + + render json: ClassroomAttendanceService.call(classrooms_api_code, start_at, end_at, year) + end + + def validate_required_params(required_params) + missing_params = required_params.select { |param| params[param].blank? } + + return false unless missing_params.any? + + render json: { error: "Os seguintes parâmetros são obrigatórios: #{missing_params.join(', ')}" }, status: :unprocessable_entity + end + end + end +end diff --git a/app/controllers/api/v2/student_classroom_attendances_controller.rb b/app/controllers/api/v2/student_classroom_attendances_controller.rb new file mode 100644 index 000000000..37d09cc69 --- /dev/null +++ b/app/controllers/api/v2/student_classroom_attendances_controller.rb @@ -0,0 +1,30 @@ +module Api + module V2 + class StudentClassroomAttendancesController < Api::V2::BaseController + respond_to :json + def index + required_params = %i[classroom_id start_at end_at year student_ids] + missing_params = validate_required_params(required_params) + + return if missing_params + classroom_api_code = params[:classroom_id] + start_at = params[:start_at] + end_at = params[:end_at] + year = params[:year] + students_api_code = params[:student_ids] + + render json: ListStudentAttendancesByClassroomService.call( + classroom_api_code, start_at, end_at, year, students_api_code + ) + end + + def validate_required_params(required_params) + missing_params = required_params.select { |param| params[param].blank? } + + return false unless missing_params.any? + + render json: { error: "Os seguintes parâmetros são obrigatórios: #{missing_params.join(', ')}" }, status: :unprocessable_entity + end + end + end +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 93a56ddcd..f2ab63d37 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,7 +2,10 @@ class ApplicationController < ActionController::Base MAX_STEPS_FOR_SCHOOL_CALENDAR = 4 - rescue_from Exception, :with => :error_generic + + unless Rails.env.development? + rescue_from Exception, :with => :error_generic + end self.responder = ApplicationResponder respond_to :html @@ -117,7 +120,8 @@ def after_sign_in_path_for(resource_or_scope) if !!current_user.receive_news == current_user.receive_news super else - flash[:info] = "É importante que seu cadastro no sistema esteja atualizado. Desta forma você poderá receber novidades sobre o produto. Por favor, atualize aqui suas preferências de e-mail." + flash[:info] = + "É importante que seu cadastro no sistema esteja atualizado. Desta forma você poderá receber novidades sobre o produto. Por favor, atualize aqui suas preferências de e-mail." edit_account_path end end @@ -348,7 +352,7 @@ def current_year_steps year = current_school_year || current_school_calendar.year steps ||= SchoolCalendar.find_by(unity_id: current_unity.id, year: year).steps steps - end + end end def first_step_start_date_for_posting @@ -424,7 +428,7 @@ def check_password_expired def check_user_first_access return if request.fullpath == edit_account_pt_br_path || - request.fullpath == account_pt_br_path + request.fullpath == account_pt_br_path return unless current_user.first_access? redirect_to edit_account_pt_br_path @@ -446,7 +450,7 @@ def weak_password?(password) return false if password.blank? if (password =~ /[A-Z]/).nil? || (password =~ /[a-z]/).nil? || (password =~ /[0-9]/).nil? || - (password =~ /[!@#\$%^&*?_~-]/).nil? + (password =~ /[!@#\$%^&*?_~-]/).nil? true else false diff --git a/app/controllers/attendance_record_report_by_students_controller.rb b/app/controllers/attendance_record_report_by_students_controller.rb index ea7b25962..5914d7d10 100644 --- a/app/controllers/attendance_record_report_by_students_controller.rb +++ b/app/controllers/attendance_record_report_by_students_controller.rb @@ -84,6 +84,12 @@ def set_options_by_user @disciplines = Discipline.by_classroom_id(@attendance_record_report_by_student_form.classroom_id) end + def fetch_linked_by_teacher + @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 + def adjusted_period(period) return Periods::FULL if period.eql?('all') || period.eql?(Periods::FULL) diff --git a/app/controllers/avaliation_recovery_diary_records_controller.rb b/app/controllers/avaliation_recovery_diary_records_controller.rb index bcc0c4b5e..a167da85b 100644 --- a/app/controllers/avaliation_recovery_diary_records_controller.rb +++ b/app/controllers/avaliation_recovery_diary_records_controller.rb @@ -12,7 +12,7 @@ def index authorize @avaliation_recovery_diary_records - @school_calendar_steps = current_school_calendar.steps + @school_calendar_steps = steps_fetcher.steps end def new @@ -25,7 +25,7 @@ def new @avaliation_recovery_diary_record.recovery_diary_record.discipline = current_user_discipline @unities = fetch_unities - @school_calendar_steps = current_school_calendar.steps + @school_calendar_steps = steps_fetcher.steps fetch_disciplines_by_classroom @@ -74,7 +74,7 @@ def edit @student_notes = fetch_student_notes @unities = fetch_unities - @school_calendar_steps = current_school_calendar.steps + @school_calendar_steps = steps_fetcher.steps @avaliations = fetch_avaliations reload_students_list @@ -128,10 +128,12 @@ def destroy def fetch_avaliation_recovery_diary_records_by_user @avaliation_recovery_diary_records = apply_scopes(AvaliationRecoveryDiaryRecord) + .select('DISTINCT ON (avaliation_recovery_diary_records.id, recovery_diary_records.recorded_at) avaliation_recovery_diary_records.*') .includes(:avaliation, recovery_diary_record: [:unity, :classroom, :discipline]) .by_unity_id(current_unity.id) .by_classroom_id(@classrooms.map(&:id)) .by_discipline_id(@disciplines.map(&:id)) + .by_teacher_id(current_teacher.id) .ordered end @@ -241,7 +243,9 @@ def reload_students_list note_student = recovery_student || recovery_diary_record.students.build(student_id: student.id, student: student) note_student.dependence = student_has_dependence?(student_enrollment, @avaliation_recovery_diary_record.recovery_diary_record.discipline) note_student.active = student_active_on_date?(student_enrollment) - note_student.exempted_from_discipline = student_exempted_from_discipline?(student_enrollment, recovery_diary_record, @avaliation_recovery_diary_record) + note_student.exempted_from_discipline = student_exempted_from_discipline?( + student_enrollment, recovery_diary_record, @avaliation_recovery_diary_record + ) @students << note_student end @@ -287,11 +291,23 @@ def student_exempted_from_discipline?(student_enrollment, recovery_diary_record, discipline_id = recovery_diary_record.discipline.id test_date = avaliation_recovery_diary_record.avaliation.test_date - step_number = avaliation_recovery_diary_record.avaliation.school_calendar.step(test_date).to_number - student_enrollment.exempted_disciplines.by_discipline(discipline_id) - .by_step_number(step_number) - .any? + step_number = fetch_step_number(avaliation_recovery_diary_record, recovery_diary_record.classroom_id, test_date) + + student_enrollment.exempted_disciplines + .by_discipline(discipline_id) + .by_step_number(step_number) + .any? + end + + def fetch_step_number(avaliation_recovery_diary_record, classroom_id, date) + school_calendar = avaliation_recovery_diary_record.avaliation.school_calendar + + school_calendar_classroom = school_calendar.classrooms.find_by_classroom_id(classroom_id) + + return school_calendar_classroom.classroom_step(date) if school_calendar_classroom.present? + + school_calendar.step(date).to_number end def any_student_exempted_from_discipline? @@ -317,12 +333,10 @@ def list_students_by_active(resource_params_hash) end def set_options_by_user - if current_user.current_role_is_admin_or_employee? - @classrooms ||= fetch_classrooms - @disciplines ||= fetch_disciplines - else - fetch_linked_by_teacher - end + return fetch_linked_by_teacher unless current_user.current_role_is_admin_or_employee? + + @classrooms ||= fetch_classrooms + @disciplines ||= fetch_disciplines end def fetch_linked_by_teacher @@ -337,4 +351,14 @@ def fetch_disciplines_by_classroom classroom = @avaliation_recovery_diary_record.recovery_diary_record.classroom @disciplines = @disciplines.by_classroom(classroom).not_descriptor end + + def steps_fetcher + classroom = if @avaliation_recovery_diary_record.present? + @avaliation_recovery_diary_record.recovery_diary_record.classroom + else + current_user_classroom + end + + @steps_fetcher ||= StepsFetcher.new(classroom) + end end diff --git a/app/controllers/avaliations_controller.rb b/app/controllers/avaliations_controller.rb index 2802c6286..2147594f0 100644 --- a/app/controllers/avaliations_controller.rb +++ b/app/controllers/avaliations_controller.rb @@ -157,10 +157,15 @@ def update def destroy authorize resource + resource_name = 'Avaliação numérica' - resource.destroy + message = if resource.destroy + { notice: t('flash.female.destroy.notice', resource_name: resource_name) } + else + { alert: t('flash.female.destroy.alert', resource_name: resource_name) } + end - respond_with resource, location: avaliations_path + redirect_to avaliations_path, message end def history @@ -300,10 +305,8 @@ def fetch_linked_by_teacher def respond_to_save if params[:commit] == I18n.t('avaliations.form.save_and_edit_daily_notes') - creator = DailyNoteCreator.new(avaliation_id: resource.id) - creator.find_or_create - - @daily_note = creator.daily_note + @daily_note = DailyNote.find_or_initialize_by(avaliation_id: resource.id) + @daily_note.save if @daily_note.new_record? if @daily_note.persisted? redirect_to edit_daily_note_path(@daily_note) diff --git a/app/controllers/daily_frequencies_controller.rb b/app/controllers/daily_frequencies_controller.rb index 58a427ad2..309381d8a 100644 --- a/app/controllers/daily_frequencies_controller.rb +++ b/app/controllers/daily_frequencies_controller.rb @@ -84,12 +84,13 @@ def edit_multiple @dependence_students = false @absence_justification = AbsenceJustification.new @absence_justification.school_calendar = current_school_calendar + enrollment_classrooms = fetch_enrollment_classrooms - student_enrollment_ids = fetch_enrollment_classrooms.map { |student_enrollment| + student_enrollment_ids = enrollment_classrooms.map { |student_enrollment| student_enrollment[:student_enrollment_id] } - student_ids = fetch_enrollment_classrooms.map { |student_enrollment| + student_ids = enrollment_classrooms.map { |student_enrollment| student_enrollment[:student].id } @@ -109,7 +110,7 @@ def edit_multiple period: @period ) - fetch_enrollment_classrooms.each do |enrollment_classroom| + enrollment_classrooms.each do |enrollment_classroom| student = enrollment_classroom[:student] student_enrollment_id = enrollment_classroom[:student_enrollment_id] activated_student = active.include?(enrollment_classroom[:student_enrollment_classroom_id]) diff --git a/app/controllers/daily_frequencies_in_batchs_controller.rb b/app/controllers/daily_frequencies_in_batchs_controller.rb index 7ac78501d..5c2137d66 100644 --- a/app/controllers/daily_frequencies_in_batchs_controller.rb +++ b/app/controllers/daily_frequencies_in_batchs_controller.rb @@ -6,7 +6,6 @@ class DailyFrequenciesInBatchsController < ApplicationController before_action :authorize_daily_frequency, only: [:new, :create, :create_or_update_multiple] before_action :require_allow_to_modify_prev_years, only: [:create, :destroy_multiple] before_action :require_valid_daily_frequency_classroom - before_action :require_valid_dates, only: [:create, :form] def new classroom_id = teacher_allocated.blank? ? nil : current_user_classroom.id @@ -22,23 +21,19 @@ def new set_options_by_user end - # TODO método duplicado para ser acessado via GET, unificar def form - start_date = params[:frequency_in_batch_form][:start_date].to_date - end_date = params[:frequency_in_batch_form][:end_date].to_date - - @dates = [*start_date..end_date] - @classroom = Classroom.includes(:unity).find(params[:frequency_in_batch_form][:classroom_id]) - @discipline = Discipline.find(params[:frequency_in_batch_form][:discipline_id]) if params[:frequency_in_batch_form][:discipline_id].present? - - return unless view_data - - render :create_or_update_multiple + create end def create start_date = params[:frequency_in_batch_form][:start_date].to_date end_date = params[:frequency_in_batch_form][:end_date].to_date + classroom_id = params[:frequency_in_batch_form][:classroom_id] + grade_id = ClassroomsGrade.find_by(classroom_id: classroom_id).grade_id + + if invalid_dates?(start_date, end_date, classroom_id, grade_id) + redirect_to(new_daily_frequencies_in_batch_path) and return + end @dates = [*start_date..end_date] @classroom = Classroom.includes(:unity).find(params[:frequency_in_batch_form][:classroom_id]) @@ -98,7 +93,7 @@ def create_or_update_multiple absence_justification.save - student_attributes[:absence_justification_student_id] = + student_attributes[:absence_justification_student_id] = absence_justification.absence_justifications_students.first.id end @@ -159,11 +154,11 @@ def destroy_multiple if @daily_frequencies.any? @daily_frequencies.each(&:destroy) - flash[:success] = t('daily_frequencies_in_batchs.destroy_multiple.success') + flash[:success] = t('.success') redirect_to new_daily_frequencies_in_batch_path else - flash[:alert] = t('daily_frequencies_in_batchs.destroy_multiple.alert') + flash[:alert] = t('.alert') redirect_to new_daily_frequencies_in_batch_path end @@ -209,7 +204,7 @@ def authorize_daily_frequency end def view_data - @period = current_teacher_period != Periods::FULL.to_i ? current_teacher_period : @classroom.period + @period = current_teacher_period == Periods::FULL.to_i ? @classroom.period : current_teacher_period @general_configuration = GeneralConfiguration.current @frequency_type = current_frequency_type(@classroom) params['dates'] = allocation_dates(@dates) @@ -232,14 +227,13 @@ def view_data return false end - fetch_student_enrollments.each do |student_enrollment| - student_enrollments_ids << student_enrollment.id - student = student_enrollment.student + enrollment_classrooms = student_enrollment_classrooms + + enrollment_classrooms.each do |student_enrollment| + student_enrollments_ids << student_enrollment[:student_enrollment].id + student = student_enrollment[:student] student_ids << student.id - type_of_teaching = student_enrollment.student_enrollment_classrooms - .by_classroom(@classroom.id) - .last - .type_of_teaching + type_of_teaching = student_enrollment[:student_enrollment_classroom].type_of_teaching next if student.blank? @@ -259,7 +253,9 @@ def view_data end dependences = student_has_dependence(student_enrollments_ids, dates) - inactives_on_date = students_inactive_on_range(student_enrollments_ids, dates) + inactives_on_date = students_inactive_on_range(enrollment_classrooms.map{|i| + 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) @@ -275,7 +271,8 @@ def view_data inactives_on_date, exempteds_from_discipline, active_searchs) end - def additional_data(dates, student_ids, dependences, inactives_on_date, exempteds_from_discipline, active_searchs) + def additional_data(dates, student_ids, dependences, inactives_on_date, exempteds_from_discipline, + active_searchs) additional_data = [] dates.each do |date| student_ids.each do |student_id| @@ -349,8 +346,8 @@ def allocation_dates(dates) else school_calendar = CurrentSchoolCalendarFetcher.new(current_unity, @classroom, current_school_year).fetch end - - valid_day = SchoolDayChecker.new(school_calendar, date, nil, nil, nil).day_allows_entry? + grade_id = @classroom.classrooms_grades.first.grade_id + valid_day = SchoolDayChecker.new(school_calendar, date, grade_id, @classroom.id, nil).day_allows_entry? next if allocations.empty? || !valid_day @@ -386,7 +383,7 @@ def build_hash(date, lesson_numbers) daily_frequencies = [] if lesson_numbers.nil? - daily_frequencies << find_or_initialize_daily_frequency_by(date, nil, @classroom.unity.id, @classroom.id, + daily_frequencies << find_or_initialize_daily_frequency_by(date, nil, @classroom.unity.id, @classroom.id, nil, @period) else lesson_numbers.each do |lesson_number| @@ -397,9 +394,9 @@ def build_hash(date, lesson_numbers) end { - 'date': date, - 'lesson_numbers': lesson_numbers, - 'daily_frequencies': daily_frequencies + date: date, + lesson_numbers: lesson_numbers, + daily_frequencies: daily_frequencies } end @@ -477,35 +474,39 @@ def mark_for_destruction_not_existing_students end end - def fetch_student_enrollments - StudentEnrollmentsList.new( - classroom: @classroom, - discipline: @discipline, + def student_enrollment_classrooms + StudentEnrollmentClassroomsRetriever.call( + classrooms: @classroom, + disciplines: @discipline, start_at: params[:start_date] || params[:frequency_in_batch_form][:start_date], end_at: params[:end_date] || params[:frequency_in_batch_form][:end_date], + show_inactive_outside_step: false, search_type: :by_date_range, - period: @period - ).student_enrollments + period: @period, + remove_duplicate_student: false + ) end - def students_inactive_on_range(student_enrollments_ids, dates) + def students_inactive_on_range(enrollment_classrooms, dates) inactives = [] dates.each do |date| - active_student_enrollments_ids = StudentEnrollment.where(id: student_enrollments_ids) - .by_classroom(@classroom) - .by_date(date) - .pluck(:id) + active_enrollments_classroom_ids = enrollment_classrooms.select do |enrollment| + enrollment.joined_at.to_date <= date && (enrollment.left_at.blank? || enrollment.left_at.to_date > date) + end.pluck(:id) - next if active_student_enrollments_ids.sort == student_enrollments_ids.sort + next if active_enrollments_classroom_ids.sort == enrollment_classrooms.pluck(:id).sort - inactives_student_enrollments_ids = student_enrollments_ids.sort - active_student_enrollments_ids.sort + inactives_enrollments_classroom_ids = enrollment_classrooms.pluck(:id) - active_enrollments_classroom_ids - inactives_students_ids = StudentEnrollment.where(id: inactives_student_enrollments_ids) - .includes(:student) - .pluck('students.id') + inactives_students_ids = Student.joins(student_enrollments: :student_enrollment_classrooms) + .where(student_enrollment_classrooms: { + id: inactives_enrollments_classroom_ids + }) + .pluck(:id) inactives << { date: date, student_ids: inactives_students_ids} + end inactives @@ -605,18 +606,17 @@ def teacher_allocated end end - def invalid_dates?(start_date, end_date) + def invalid_dates?(start_date, end_date, classroom_id, grade_id) if start_date.nil? || end_date.nil? flash[:error] = t('daily_frequencies_in_batchs.create_or_update_multiple.blank_dates') return true end - unless SchoolDayChecker.new(current_school_calendar, start_date, nil, nil, nil).school_day? + unless SchoolDayChecker.new(current_school_calendar, start_date, grade_id, classroom_id, nil).school_day? flash[:error] = t('daily_frequencies_in_batchs.create_or_update_multiple.initial_date_no_school_day') return true end - - unless SchoolDayChecker.new(current_school_calendar, end_date, nil, nil, nil).school_day? + unless SchoolDayChecker.new(current_school_calendar, end_date, grade_id, classroom_id, nil).school_day? flash[:error] = t('daily_frequencies_in_batchs.create_or_update_multiple.final_date_no_school_day') return true end @@ -632,17 +632,8 @@ def invalid_dates?(start_date, end_date) end end - def require_valid_dates - start_date = params[:frequency_in_batch_form][:start_date].to_date - end_date = params[:frequency_in_batch_form][:end_date].to_date - - if invalid_dates?(start_date, end_date) - redirect_to(new_daily_frequencies_in_batch_path) and return - end - end - def fetch_linked_by_teacher - @fetch_linked_by_teacher ||= TeacherClassroomAndDisciplineFetcher.fetch!(current_teacher.id, current_unity, + @fetch_linked_by_teacher ||= TeacherClassroomAndDisciplineFetcher.fetch!(current_teacher.id, current_unity, current_school_year) @disciplines = [] @classrooms = [] diff --git a/app/controllers/daily_note_students_controller.rb b/app/controllers/daily_note_students_controller.rb index abb126121..06d04445e 100644 --- a/app/controllers/daily_note_students_controller.rb +++ b/app/controllers/daily_note_students_controller.rb @@ -128,7 +128,13 @@ def fetch_student_enrollments(classroom, avaliation, discipline, date) def student_exempted_from_discipline?(student_enrollment, daily_note) discipline_id = daily_note.discipline.id test_date = daily_note.avaliation.test_date - step_number = daily_note.avaliation.school_calendar.step(test_date).to_number + classroom = daily_note.classroom + + step_number = if classroom.calendar.present? + classroom.calendar.classroom_step(test_date).to_number + else + daily_note.avaliation.school_calendar.step(test_date).to_number + end student_enrollment.exempted_disciplines.by_discipline(discipline_id) .by_step_number(step_number) diff --git a/app/controllers/daily_notes_controller.rb b/app/controllers/daily_notes_controller.rb index c13ff8dd6..da1498a88 100644 --- a/app/controllers/daily_notes_controller.rb +++ b/app/controllers/daily_notes_controller.rb @@ -32,9 +32,9 @@ def new end def create - creator = DailyNoteCreator.new(resource_params) - creator.find_or_create - @daily_note = creator.daily_note + @daily_note = DailyNote.find_or_initialize_by(resource_params) + @daily_note.save if @daily_note.new_record? + reload_students_list if @daily_note.persisted? redirect_to edit_daily_note_path(@daily_note) @@ -48,34 +48,7 @@ def edit authorize @daily_note - student_enrollments = fetch_student_enrollments - - @students = [] - - student_enrollments.each do |student_enrollment| - if student = Student.find_by_id(student_enrollment.student_id) - note_student = (@daily_note.students.where(student_id: student.id).first || @daily_note.students.build(student_id: student.id, student: student)) - note_student.active = student_active_on_date?(student_enrollment) - note_student.dependence = student_has_dependence?(student_enrollment, @daily_note.discipline) - note_student.exempted = student_exempted_from_avaliation?(student.id) - note_student.exempted_from_discipline = student_exempted_from_discipline?(student_enrollment, @daily_note) - note_student.in_active_search = ActiveSearch.new.in_active_search?(student_enrollment.id, @daily_note.avaliation.test_date) - - @students << note_student - end - end - - @normal_students = [] - @dependence_students = [] - @any_exempted_student = any_exempted_student? - @any_inactive_student = any_inactive_student? - @any_student_exempted_from_discipline = any_student_exempted_from_discipline? - @any_in_active_search = any_in_active_search? - - @students.each do |student| - @normal_students << student if !student.dependence - @dependence_students << student if student.dependence - end + reload_students_list end def update @@ -169,8 +142,8 @@ def fetch_classrooms protected - def fetch_student_enrollments - @students_enrollments ||= StudentEnrollmentsRetriever.call( + def set_enrollment_classrooms + @student_enrollment_classrooms ||= StudentEnrollmentClassroomsRetriever.call( classrooms: @daily_note.classroom, grades: @daily_note.avaliation.grade_ids, disciplines: @daily_note.discipline, @@ -181,52 +154,28 @@ def fetch_student_enrollments end def reload_students_list - @students = [] - - @daily_note.students.each_with_index do |note_student, index| - if student = Student.find_by_id(note_student.student_id) - student_enrollment = StudentEnrollment - .by_student(note_student.student_id) - .by_classroom(@daily_note.classroom_id) - .by_discipline(@daily_note.discipline_id) - .by_score_type(StudentEnrollmentScoreTypeFilters::NUMERIC, @daily_note.classroom_id) - .active - .first - - note_student.dependence = student_has_dependence?(student_enrollment, @daily_note.discipline) - note_student.exempted = student_exempted_from_avaliation?(student.id) - note_student.active = student_active_on_date?(student_enrollment) - - @students << note_student - end - end - - @normal_students = [] - @dependence_students = [] - @any_exempted_student = any_exempted_student? - @any_inactive_student = any_inactive_student? - - @students.each do |student| - @normal_students << student if !student.dependence - @dependence_students << student if student.dependence + set_students_and_info + set_student_enrollments_data + + 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.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 + note_student.exempted_from_discipline = @exempted_from_discipline[student_enrollment_id] ? true : false + note_student.in_active_search = @active_search[@daily_note.test_date]&.include?(student_enrollment_id) + + @normal_students << note_student if !note_student.dependence + @dependence_students << note_student if note_student.dependence + @students << note_student end - end - - def student_active_on_date?(student_enrollment) - StudentEnrollment - .where(id: student_enrollment) - .by_classroom(@daily_note.classroom) - .by_date(@daily_note.avaliation.test_date) - .any? - end - def student_displayable_as_inactive?(student_enrollment) - StudentEnrollment - .where(id: student_enrollment) - .by_classroom(@daily_note.classroom) - .by_discipline(@daily_note.discipline) - .show_as_inactive - .any? + @any_exempted_student = @students.select(&:exempted).any? + @any_inactive_student = @students.reject(&:active).any? + @any_student_exempted_from_discipline = @students.select(&:exempted_from_discipline).any? + @any_in_active_search = @students.select(&:in_active_search).any? end def configuration @@ -284,71 +233,72 @@ def fetch_linked_by_teacher end def destroy_students_not_found + student_params = resource_params[:students_attributes]&.to_h + @daily_note.students.each do |student| - student_exists = resource_params[:students_attributes].any? do |student_params| - student_params.last[:student_id].to_i == student.student.id + student_exists = student_params.any? do |_, params| + params[:student_id].to_i == student.student.id end student.destroy unless student_exists || student.transfer_note.present? end end - def student_exempted_from_avaliation?(student_id) - avaliation_id = @daily_note.avaliation_id - is_exempted = AvaliationExemption - .by_student(student_id) - .by_avaliation(avaliation_id) - .any? - is_exempted - end + def delete_note(daily_note_id, student_id) + return unless (student_note = DailyNoteStudent.find_by(daily_note_id: daily_note_id, student_id: student_id)) - def any_exempted_student? - avaliation_id = @daily_note.avaliation_id - any_exempted_student = AvaliationExemption - .by_avaliation(avaliation_id) - .any? - any_exempted_student + student_note.update!(note: nil) end - def student_has_dependence?(student_enrollment, discipline) - StudentEnrollmentDependence - .by_student_enrollment(student_enrollment) - .by_discipline(discipline) - .any? - end + def set_students_and_info + @students = [] + @normal_students = [] + @dependence_students = [] - def any_inactive_student? - any_inactive_student = false - if @students - @students.each do |student| - any_inactive_student = true if !student.active - end - end - any_inactive_student + @discipline = @daily_note.discipline + @avaliation_id = @daily_note.avaliation_id + @test_date = @daily_note.avaliation.test_date + @step = StepsFetcher.new(@daily_note.classroom).step_by_date(@test_date) end - def student_exempted_from_discipline?(student_enrollment, daily_note) - discipline_id = daily_note.discipline.id - test_date = daily_note.avaliation.test_date - step = StepsFetcher.new(daily_note.classroom).step_by_date(test_date) - step_number = step.to_number - - student_enrollment.exempted_disciplines.by_discipline(discipline_id) - .by_step_number(step_number) - .any? + def set_student_enrollments_data + @student_enrollment_ids = set_enrollment_classrooms.map { |student_enrollment| + student_enrollment[:student_enrollment].id + } + @student_ids = set_enrollment_classrooms.map { |student_enrollment| + student_enrollment[:student].id + } + @dependencies = StudentsInDependency.call(student_enrollments: @student_enrollment_ids, disciplines: @discipline) + @exempted_from_discipline = StudentsExemptFromDiscipline.call( + student_enrollments: @student_enrollment_ids, discipline: @discipline, step: @step + ) + @exempted_from_avaliation = students_exempted_from_avaliations(@avaliation_id, @student_ids) + @active = ActiveStudentsOnDate.call(student_enrollments: @student_enrollment_ids, date: @test_date) + @active_search = in_active_searches end - def any_student_exempted_from_discipline? - (@students || []).any?(&:exempted_from_discipline) + def in_active_searches + @in_active_searches ||= ActiveSearch.new.enrollments_in_active_search?(@student_enrollment_ids, @test_date) end - def delete_note(daily_note_id, student_id) - return unless (student_note = DailyNoteStudent.find_by(daily_note_id: daily_note_id, student_id: student_id)) + def students_exempted_from_avaliations(avaliation_id, student_ids) + students_exempt_from_avaliation = {} - student_note.update!(note: nil) + exemptions = AvaliationExemption.by_student(student_ids).by_avaliation(avaliation_id) + + return {} unless exemptions + + exemptions.each do |exempt| + students_exempt_from_avaliation[exempt.student_id] ||= [] + students_exempt_from_avaliation[exempt.student_id] << exempt.avaliation_id + end end - def any_in_active_search? - (@students || []).any?(&:in_active_search) + 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 a42032e26..55741198e 100644 --- a/app/controllers/descriptive_exams_controller.rb +++ b/app/controllers/descriptive_exams_controller.rb @@ -6,13 +6,16 @@ class DescriptiveExamsController < ApplicationController def new @descriptive_exam = DescriptiveExam.new( - classroom_id: current_user_classroom.id, - discipline_id: current_user_discipline.id + classroom_id: current_user_classroom.id ) 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 + unless current_user.current_role_is_admin_or_employee? classroom_id = @descriptive_exam.classroom_id @disciplines = @disciplines.by_classroom_id(classroom_id).not_descriptor @@ -51,9 +54,8 @@ def update regular_expression = /contenteditable(([ ]*)?\=?([ ]*)?("(.*)"|'(.*)'))/ @descriptive_exam.students.each do |exam_student| value_by_student = resource_params[:students_attributes].values.detect do |student| - student[:student_id] == exam_student.student_id.to_s + student[:student_id] == exam_student.student_id.to_s && student[:inactive_student] == 'false' end - exam_student.value = value_by_student['value'] if value_by_student.present? exam_student.value.gsub!(regular_expression, '') if exam_student.value.present? end @@ -130,7 +132,7 @@ def resource_params :recorded_at, :opinion_type, students_attributes: [ - :id, :student_id, :value, :dependence + :id, :student_id, :value, :dependence, :inactive_student ] ) end @@ -177,7 +179,8 @@ def find_or_create_descriptive_exam end def opinion_type_by_year?(opinion_type = nil) - [OpinionTypes::BY_YEAR, OpinionTypes::BY_YEAR_AND_DISCIPLINE].include?(opinion_type || @descriptive_exam.opinion_type) + [OpinionTypes::BY_YEAR, + OpinionTypes::BY_YEAR_AND_DISCIPLINE].include?(opinion_type || @descriptive_exam.opinion_type) end def recorded_at_by_step @@ -221,14 +224,15 @@ def fetch_students enrollment_classrooms_list.each do |enrollment_classroom| student = enrollment_classroom[:student] student_enrollment = enrollment_classroom[:student_enrollment] + left_at = enrollment_classroom[:student_enrollment_classroom].left_at.to_date + exam_student = (@descriptive_exam.students.where(student_id: student.id).first || @descriptive_exam.students.build(student_id: student.id)) exam_student.dependence = student_has_dependence?(student_enrollment, @descriptive_exam.discipline) exam_student.exempted_from_discipline = student_exempted_from_discipline?(student_enrollment) regular_expression = /contenteditable(([ ]*)?\=?([ ]*)?("(.*)"|'(.*)'))/ exam_student.value = exam_student.value.gsub(regular_expression, '') if exam_student.value.present? + exam_student.inactive_student = left_at.present? && left_at < @descriptive_exam.step.try(:end_at) - left_at = enrollment_classroom[:student_enrollment_classroom].left_at.to_date - exam_student.active_student = left_at.present? && left_at < @descriptive_exam.step.try(:end_at) @students << exam_student end diff --git a/app/controllers/disciplines_controller.rb b/app/controllers/disciplines_controller.rb index ef41ce197..f2a1f2603 100644 --- a/app/controllers/disciplines_controller.rb +++ b/app/controllers/disciplines_controller.rb @@ -1,7 +1,9 @@ class DisciplinesController < ApplicationController respond_to :json - has_scope :by_unity_id + has_scope :by_unity_id do |controller, scope, value| + scope.by_unity_id(value, controller.params[:year]) + end has_scope :by_teacher_id has_scope :by_grade has_scope :by_classroom @@ -55,7 +57,7 @@ def search end def search_by_grade_and_unity - @disciplines = apply_scopes(Discipline).where(teacher_discipline_classrooms: { teacher_id: current_user.teacher_id }).ordered.uniq + @disciplines = apply_scopes(Discipline).ordered.distinct render json: @disciplines end diff --git a/app/controllers/exam_record_report_controller.rb b/app/controllers/exam_record_report_controller.rb index 6b20597ed..a9df534ee 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? @@ -58,7 +58,7 @@ def build_by_school_steps @exam_record_report_form.step, current_test_setting_step(@exam_record_report_form.step), @exam_record_report_form.daily_notes, - @exam_record_report_form.students_enrollments, + @exam_record_report_form.filter_unique_students, @exam_record_report_form.complementary_exams, @exam_record_report_form.school_term_recoveries, @exam_record_report_form.recovery_lowest_notes?, @@ -74,7 +74,7 @@ def build_by_classroom_steps @exam_record_report_form.classroom_step, current_test_setting_step(@exam_record_report_form.classroom_step), @exam_record_report_form.daily_notes_classroom_steps, - @exam_record_report_form.students_enrollments, + @exam_record_report_form.filter_unique_students, @exam_record_report_form.complementary_exams, @exam_record_report_form.school_term_recoveries, @exam_record_report_form.recovery_lowest_notes?, @@ -83,7 +83,8 @@ def build_by_classroom_steps 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) classroom_id = @exam_record_report_form.classroom_id @disciplines ||= @fetch_linked_by_teacher[:disciplines].by_classroom_id(classroom_id) .not_descriptor diff --git a/app/controllers/school_term_recovery_diary_records_controller.rb b/app/controllers/school_term_recovery_diary_records_controller.rb index 09216a028..9d6cfbd29 100644 --- a/app/controllers/school_term_recovery_diary_records_controller.rb +++ b/app/controllers/school_term_recovery_diary_records_controller.rb @@ -44,7 +44,7 @@ def new return if performed? @number_of_decimal_places = current_test_setting&.number_of_decimal_places || - current_test_setting_step(current_year_last_step)&.number_of_decimal_places + current_test_setting_step(current_year_last_step)&.number_of_decimal_places end def create @@ -91,11 +91,10 @@ def edit students_in_recovery = fetch_students_in_recovery mark_students_not_in_recovery_for_destruction(students_in_recovery) mark_exempted_disciplines(students_in_recovery) - add_missing_students(students_in_recovery) @any_student_exempted_from_discipline = any_student_exempted_from_discipline? @number_of_decimal_places = current_test_setting&.number_of_decimal_places || - current_test_setting_step(step)&.number_of_decimal_places + current_test_setting_step(step)&.number_of_decimal_places end def update @@ -202,35 +201,22 @@ def fetch_students_in_recovery end def mark_students_not_in_recovery_for_destruction(students_in_recovery) + students_in_recovery_ids = students_in_recovery.map { |s| s[:student].id } + @students.each do |student| - is_student_in_recovery = students_in_recovery.any? do |student_in_recovery| - student.student.id == student_in_recovery.id + unless students_in_recovery_ids.include?(student.student_id) + student.mark_for_destruction end - - student.mark_for_destruction unless is_student_in_recovery end end def mark_exempted_disciplines(students_in_recovery) - @students.each do |student| - exempted_from_discipline = students_in_recovery.find do |student_in_recovery| - student_in_recovery.id == student.student_id - end.try(:exempted_from_discipline) - - student.exempted_from_discipline = exempted_from_discipline - end - end - - def add_missing_students(students_in_recovery) - students_missing = students_in_recovery.select do |student_in_recovery| - @students.none? do |student| - student.student.id == student_in_recovery.id - end - end + students_in_recovery_map = students_in_recovery.index_by { |s| s[:student].id } - students_missing.each do |student_missing| - student = @school_term_recovery_diary_record.recovery_diary_record.students.build(student: student_missing) - @students << student + @students.each do |student| + student.exempted_from_discipline = students_in_recovery_map.dig( + student.student_id, :exempted_from_discipline + ) || false end end @@ -242,50 +228,32 @@ def api_configuration IeducarApiConfiguration.current end - def fetch_student_enrollments + def fetch_student_enrollment_classrooms recovery_diary_record = @school_term_recovery_diary_record.recovery_diary_record return unless recovery_diary_record.recorded_at - StudentEnrollmentsList.new( - classroom: recovery_diary_record.classroom, - discipline: recovery_diary_record.discipline, + students = 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 - ).student_enrollments + ) + + 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 - return unless (student_enrollments = fetch_student_enrollments) - recovery_diary_record = @school_term_recovery_diary_record.recovery_diary_record - return unless recovery_diary_record.recorded_at - @students = [] - - student_enrollments.each do |student_enrollment| - next unless (student = Student.find_by(id: student_enrollment.student_id)) - - recovery_student = recovery_diary_record.students.select { |student_recovery| - student_recovery.student_id == student.id - }.first - note_student = recovery_student || - recovery_diary_record.students.build(student: student) - - note_student.active = student_active_on_date?(student_enrollment, recovery_diary_record) - - @students << note_student + @students = fetch_student_enrollment_classrooms.map do |student| + recovery_diary_record.students.find_or_initialize_by(student: student[:student]) end - - @students - end - - def student_active_on_date?(student_enrollment, recovery_diary_record) - StudentEnrollment.where(id: student_enrollment) - .by_classroom(recovery_diary_record.classroom) - .by_date(recovery_diary_record.recorded_at) - .any? end def set_options_by_user @@ -308,22 +276,31 @@ def fetch_linked_by_teacher end def set_school_term_recovery_diary_records - @school_term_recovery_diary_records = apply_scopes(SchoolTermRecoveryDiaryRecord) - .includes( - recovery_diary_record: [ - :unity, - :classroom, - :discipline - ] - ) - .by_classroom_id(@classrooms.map(&:id)) - .by_discipline_id(@disciplines.map(&:id)) - .ordered - .distinct - - unless @admin_or_teacher - @school_term_recovery_diary_records = @school_term_recovery_diary_records.by_teacher_id(current_teacher.id).distinct - end + @school_term_recovery_diary_records = if @admin_or_teacher + school_term_recovery_diary_records_for_admin + else + school_term_recovery_diary_records_for_teacher + end + + @school_term_recovery_diary_records = @school_term_recovery_diary_records.ordered.distinct + end + + def school_term_recovery_diary_records_for_teacher + base_query + .joins(recovery_diary_record: :classroom) + .joins('INNER JOIN teacher_discipline_classrooms tdc ON tdc.classroom_id = classrooms.id AND tdc.discipline_id = recovery_diary_records.discipline_id') + .where('tdc.teacher_id = ? AND tdc.discarded_at IS NULL', current_teacher.id) + end + + def school_term_recovery_diary_records_for_admin + base_query + .by_classroom_id(@classrooms.pluck(:id)) + .by_discipline_id(@disciplines.pluck(:id)) + end + + def base_query + apply_scopes(SchoolTermRecoveryDiaryRecord) + .includes(recovery_diary_record: [:unity, :classroom, :discipline]) end def fetch_disciplines_by_classroom diff --git a/app/controllers/students_controller.rb b/app/controllers/students_controller.rb index 748ec1f22..6ab3cbcac 100644 --- a/app/controllers/students_controller.rb +++ b/app/controllers/students_controller.rb @@ -76,6 +76,10 @@ def in_recovery params[:date].to_date.to_s ).fetch + @students = @students.select do |student| + student[:student_enrollment_classroom].left_at.blank? || student[:student_enrollment_classroom].left_at.to_date >= params[:date].to_date + end.pluck(:student) + render( json: @students, each_serializer: StudentInRecoverySerializer, diff --git a/app/forms/exam_record_report_form.rb b/app/forms/exam_record_report_form.rb index 2618876cc..7ea521a16 100644 --- a/app/forms/exam_record_report_form.rb +++ b/app/forms/exam_record_report_form.rb @@ -16,7 +16,7 @@ class ExamRecordReportForm validate :must_have_daily_notes def daily_notes - return unless step + return if step.blank? @daily_notes = DailyNote.by_unity_id(unity_id) .by_classroom_id(classroom_id) @@ -26,9 +26,8 @@ def daily_notes end def recovery_lowest_notes? - return unless step + return if step.blank? - classroom = Classroom.find(classroom_id) @recovery_lowest_notes = AvaliationRecoveryLowestNote.by_unity_id(unity_id) .by_classroom_id(classroom_id) .by_discipline_id(discipline_id) @@ -37,23 +36,15 @@ def recovery_lowest_notes? end def lowest_notes - return unless step - - classroom = Classroom.find(classroom_id) + return if step.blank? lowest_notes = {} - RecoveryDiaryRecordStudent.by_student_id(students_enrollments.map(&:student_id)) - .joins(:recovery_diary_record) - .merge( - RecoveryDiaryRecord.by_discipline_id(discipline_id) - .by_classroom_id(classroom_id) - .joins(:students, :avaliation_recovery_lowest_note) - .merge( - AvaliationRecoveryLowestNote - .by_step_id(classroom, step.id) - ) - ).each do |recovery_diary_record| + recovery_diary_record_students = RecoveryDiaryRecordStudent.by_student_id(student_ids) + .joins(:recovery_diary_record) + .merge(recovery_diary_records) + + recovery_diary_record_students.each do |recovery_diary_record| student_data = {recovery_diary_record.student_id => recovery_diary_record.score} lowest_notes = lowest_notes.merge(student_data) end @@ -62,7 +53,7 @@ def lowest_notes end def daily_notes_classroom_steps - return unless classroom_step + return if classroom_step.blank? @daily_notes = DailyNote.by_unity_id(unity_id) .by_classroom_id(classroom_id) @@ -71,28 +62,39 @@ def daily_notes_classroom_steps .order_by_avaliation_test_date end - def students_enrollments - StudentEnrollmentsList.new( - classroom: classroom_id, - discipline: discipline_id, + def info_students + @student_enrollment_classrooms ||= StudentEnrollmentClassroomsRetriever.call( + classrooms: classroom_id, + disciplines: discipline_id, start_at: classroom_step.try(:start_at) || step.start_at, end_at: classroom_step.try(:end_at) || step.end_at, score_type: StudentEnrollmentScoreTypeFilters::NUMERIC, search_type: :by_date_range, - show_inactive: false - ).student_enrollments + include_inactive: false + ) + end + + def filter_unique_students + info_students.each_with_object({}) do |student, unique_students| + student_id = student[:student].id + unique_students[student_id] ||= student + end.values + end + + def student_ids + info_students.map { |info| info[:student].id } end def step - return unless school_calendar_step_id + return if school_calendar_step_id.blank? - SchoolCalendarStep.find(school_calendar_step_id) + @step ||= SchoolCalendarStep.find(school_calendar_step_id) end def classroom_step - return unless school_calendar_classroom_step_id + return if school_calendar_classroom_step_id.blank? - SchoolCalendarClassroomStep.find(school_calendar_classroom_step_id) + @step ||= SchoolCalendarClassroomStep.find(school_calendar_classroom_step_id) end def complementary_exams @@ -106,6 +108,7 @@ def complementary_exams def school_term_recoveries return [] unless GeneralConfiguration.current.show_school_term_recovery_in_exam_record_report? + @school_term_recoveries ||= SchoolTermRecoveryDiaryRecord .includes(recovery_diary_record: :discipline) .by_unity_id(unity_id) @@ -118,7 +121,7 @@ def school_term_recoveries private def must_have_daily_notes - return unless errors.blank? + return if errors.present? notes = daily_notes_classroom_steps || daily_notes @@ -127,19 +130,14 @@ def must_have_daily_notes end end - def remove_duplicated_enrollments(students_enrollments) - students_enrollments = students_enrollments.select do |student_enrollment| - enrollments_for_student = StudentEnrollment - .by_student(student_enrollment.student_id) - .by_classroom(classroom_id) - - if enrollments_for_student.count > 1 - enrollments_for_student.last != student_enrollment - else - true - end - end + def recovery_diary_records + RecoveryDiaryRecord.by_discipline_id(discipline_id) + .by_classroom_id(classroom_id) + .joins(:students, :avaliation_recovery_lowest_note) + .merge(AvaliationRecoveryLowestNote.by_step_id(classroom, step.id)) + end - students_enrollments + def classroom + @classroom ||= Classroom.find(classroom_id) end end diff --git a/app/helpers/daily_frequencies_in_batchs_helper.rb b/app/helpers/daily_frequencies_in_batchs_helper.rb new file mode 100644 index 000000000..5dd5ebf69 --- /dev/null +++ b/app/helpers/daily_frequencies_in_batchs_helper.rb @@ -0,0 +1,36 @@ +module DailyFrequenciesInBatchsHelper + def data_additional(date, student) + additional_class = nil + tooltip = nil + + @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] + end + end + + { + response_class: additional_class, + response_tooltip: tooltip + } + end + + def custom_student_name(student) + student_name = student[:student][:name] + color = false + + @additional_data.each do |additional_data| + if additional_data[:student_id] == student[:student][:id] + student_name = '*' + student[:student][:name] + color = '#a90329' + end + end + + { + name: student_name, + color: color + } + end +end + diff --git a/app/helpers/data_exportations_helper.rb b/app/helpers/data_exportations_helper.rb new file mode 100644 index 000000000..c4efd002c --- /dev/null +++ b/app/helpers/data_exportations_helper.rb @@ -0,0 +1,24 @@ +module DataExportationsHelper + def formatted_backup_link(backup) + return unless backup.created_at.present? + + link_to I18n.l(backup.created_at), backup.backup_file_url + end + + def backup_status_message(backup) + return formatted_backup_link(backup) if backup.completed? + return "Erro: #{backup.error_message}" if backup.error? + end + + def backup_button_or_status(form, backup, backup_type) + return exporting_button if backup.started? + + form.submit 'Exportar', name: "backup_type[#{backup_type}]", class: 'btn bg-color-red txt-color-white' + end + + def exporting_button + link_to '#', class: 'btn bg-color-red txt-color-white' do + content_tag(:i, '', class: 'fa fa-cog fa-spin') + ' Exportando...' + end + end +end diff --git a/app/models/descriptive_exam_student.rb b/app/models/descriptive_exam_student.rb index 742696351..624d15c2a 100644 --- a/app/models/descriptive_exam_student.rb +++ b/app/models/descriptive_exam_student.rb @@ -4,7 +4,7 @@ class DescriptiveExamStudent < ApplicationRecord audited associated_with: :descriptive_exam, except: [:descriptive_exam_id, :dependence] - attr_accessor :exempted_from_discipline, :active_student + attr_accessor :exempted_from_discipline, :inactive_student belongs_to :descriptive_exam belongs_to :student diff --git a/app/models/discipline.rb b/app/models/discipline.rb index 1eb4dcdb3..59f75a579 100644 --- a/app/models/discipline.rb +++ b/app/models/discipline.rb @@ -18,10 +18,10 @@ class Discipline < ApplicationRecord validates :description, :api_code, :knowledge_area_id, presence: true validates :api_code, uniqueness: true - scope :by_unity_id, lambda { |unity_id, year| by_unity_id(unity_id, year) } + scope :by_unity_id, lambda { |unity_id, year| self.by_unity_year(unity_id, year)} scope :by_teacher_id, lambda { |teacher_id, year| - joins(:teacher_discipline_classrooms).where(teacher_discipline_classrooms: - { teacher_id: teacher_id , year: year}).distinct + joins(:teacher_discipline_classrooms) + .where(teacher_discipline_classrooms: { teacher_id: teacher_id, year: year}).distinct } scope :by_classroom_id, lambda { |classroom_id| joins(:teacher_discipline_classrooms).where(teacher_discipline_classrooms: { classroom_id: classroom_id }).distinct @@ -110,17 +110,17 @@ def self.grouped_by_knowledge_area private - def self.by_unity_id(unity_id, year) + def self.by_unity_year(unity_id, year) joins(:teacher_discipline_classrooms).joins( - arel_table.join(Classroom.arel_table) - .on( - Classroom.arel_table[:id] - .eq(TeacherDisciplineClassroom.arel_table[:classroom_id]) - ) - .join_sources - ) - .where(classrooms: { unity_id: unity_id, year: year}) - .distinct + arel_table.join(Classroom.arel_table) + .on( + Classroom.arel_table[:id] + .eq(TeacherDisciplineClassroom.arel_table[:classroom_id]) + ) + .join_sources + ) + .where(classrooms: { unity_id: unity_id, year: year}) + .distinct end def self.by_grade(grade_id) diff --git a/app/models/general_configuration.rb b/app/models/general_configuration.rb index 82b7e2d25..a1c4dca9f 100644 --- a/app/models/general_configuration.rb +++ b/app/models/general_configuration.rb @@ -1,7 +1,7 @@ class GeneralConfiguration < ActiveRecord::Base acts_as_copy_target - audited + audited except: :backup_file include Audit diff --git a/app/models/school_calendar_classroom_step.rb b/app/models/school_calendar_classroom_step.rb index 0d6b8b5e9..becc8f901 100644 --- a/app/models/school_calendar_classroom_step.rb +++ b/app/models/school_calendar_classroom_step.rb @@ -56,10 +56,6 @@ def school_calendar_day_allows_entry?(date) school_calendar.day_allows_entry?(date, classroom.grade_ids, classroom_id) end - def first_school_calendar_date - school_calendar.school_day_checker(start_at, classroom.grade_ids, classroom_id).next_school_day - end - def school_calendar school_calendar_classroom.school_calendar if school_calendar_classroom.present? end diff --git a/app/models/school_calendar_step.rb b/app/models/school_calendar_step.rb index f046b89e1..0f6a0cccd 100644 --- a/app/models/school_calendar_step.rb +++ b/app/models/school_calendar_step.rb @@ -51,10 +51,6 @@ def school_calendar_day_allows_entry?(date) school_calendar.day_allows_entry?(date) end - def first_school_calendar_date - school_calendar.school_day_checker(start_at).next_school_day - end - def school_day_dates return if start_at.blank? || end_at.blank? || school_calendar.blank? diff --git a/app/models/teaching_plan.rb b/app/models/teaching_plan.rb index c6a167db4..1d916f239 100644 --- a/app/models/teaching_plan.rb +++ b/app/models/teaching_plan.rb @@ -22,9 +22,9 @@ class TeachingPlan < ApplicationRecord validates :school_term_type_step, presence: { unless: :yearly? } has_many :contents_teaching_plans, dependent: :destroy - deferred_has_many :contents, through: :contents_teaching_plans + deferred_has_many :contents, through: :contents_teaching_plans, dependent: :destroy has_many :objectives_teaching_plans, dependent: :destroy - deferred_has_many :objectives, through: :objectives_teaching_plans + deferred_has_many :objectives, through: :objectives_teaching_plans, dependent: :destroy has_many :teaching_plan_attachments, dependent: :destroy has_one :discipline_teaching_plan, dependent: :restrict_with_error diff --git a/app/models/teaching_plan_attachment.rb b/app/models/teaching_plan_attachment.rb index fd9e0c562..66cbf2f42 100644 --- a/app/models/teaching_plan_attachment.rb +++ b/app/models/teaching_plan_attachment.rb @@ -1,7 +1,30 @@ class TeachingPlanAttachment < ApplicationRecord + audited associated_with: :teaching_plan, except: + [:attachment_updated_at, :attachment_file_name_with_hash, :attachment, :teaching_plan_id] + belongs_to :teaching_plan mount_uploader :attachment, DocUploader delegate :filename, to: :attachment + + validate :attachment_extension_whitelist + + before_save :set_attachment_attributes + + private + + def attachment_extension_whitelist + return unless attachment.present? && !attachment.file.extension.match(/\A(jpeg|jpg|png|gif|pdf|odt|doc|docx|ods|xls|xlsx|odp|ppt|pptx|odg|xml|csv)\z/i) + + errors.add(:attachment, "Somente arquivos nos formatos JPEG, JPG, PNG, GIF, PDF, ODT, DOC, DOCX, ODS, XLS, XLSX, ODP, PPT, PPTX, ODG, XML, or CSV file") + end + + def set_attachment_attributes + return unless attachment.present? && attachment.file.present? + + self.attachment_file_name = attachment.file.filename + self.attachment_content_type = attachment.file.content_type + self.attachment_file_size = "#{attachment.file.size} kB" + end end diff --git a/app/models/user.rb b/app/models/user.rb index 1f4dbc5f8..a9d008d08 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -28,7 +28,6 @@ class User < ApplicationRecord belongs_to :student belongs_to :teacher - belongs_to :assumed_teacher, foreign_key: :assumed_teacher_id, class_name: 'Teacher' belongs_to :current_discipline, foreign_key: :current_discipline_id, class_name: 'Discipline' belongs_to :current_knowledge_area, foreign_key: :current_knowledge_area_id, class_name: 'KnowledgeArea' @@ -63,7 +62,6 @@ class User < ApplicationRecord validates :password, length: { minimum: 8 }, allow_blank: true validates :login, uniqueness: true, allow_blank: true validates :teacher_id, uniqueness: true, allow_blank: true - validates :student, presence: true, if: :only_student? validates_associated :user_roles @@ -73,6 +71,7 @@ class User < ApplicationRecord validate :validate_receive_news_fields, if: :has_to_validate_receive_news_fields? validate :can_not_be_a_cpf validate :can_not_be_an_email + validate :validate_student_presence, if: :only_student? scope :ordered, -> { order(arel_table[:fullname].asc) } scope :email_ordered, -> { order(email: :asc) } @@ -120,7 +119,9 @@ def self.to_csv CSV.generate(headers: true) do |csv| csv << attributes - all.includes(:teacher, :student, user_roles: [:role, :unity]).find_each do |user| + users = all.includes(:teacher, :student, user_roles: [:role, :unity]).ordered + + users.each do |user| csv << [ user.first_name, user.last_name, @@ -150,7 +151,7 @@ def self.find_for_authentication(conditions) end def first_access? - email.include?('ambiente.portabilis.com.br') && + email&.include?('ambiente.portabilis.com.br') && created_at.to_date >= last_password_change.to_date end @@ -504,4 +505,8 @@ def remove_spaces_from_name write_attribute(:first_name, first_name.squish) if first_name.present? write_attribute(:last_name, last_name.squish) if last_name.present? end + + def validate_student_presence + errors.add(:student, :blank) if student.blank? + end end diff --git a/app/presenters/descriptive_exam_student_presenter.rb b/app/presenters/descriptive_exam_student_presenter.rb index e513f3e59..10c0b8855 100644 --- a/app/presenters/descriptive_exam_student_presenter.rb +++ b/app/presenters/descriptive_exam_student_presenter.rb @@ -14,7 +14,7 @@ def student_name_class def student_name if dependence "*#{student.api_code} - #{student}" - elsif exempted_from_discipline || active_student + elsif exempted_from_discipline || inactive_student "****#{student.api_code} - #{student}" else "#{student.api_code} - #{student}" diff --git a/app/queries/observation_record_report_query.rb b/app/queries/observation_record_report_query.rb index d8f1fad6a..9f2b3fec4 100644 --- a/app/queries/observation_record_report_query.rb +++ b/app/queries/observation_record_report_query.rb @@ -18,8 +18,8 @@ def observation_diary_records Classroom.by_unity(unity_id).pluck(:id) end end - relation = ObservationDiaryRecord.includes(notes: :students) + .by_teacher(teacher_id) .by_classroom(classroom_id) .where(date: start_at..end_at) .order(:date) diff --git a/app/reports/attendance_record_report.rb b/app/reports/attendance_record_report.rb index 58a3b7262..2159906fb 100644 --- a/app/reports/attendance_record_report.rb +++ b/app/reports/attendance_record_report.rb @@ -140,6 +140,10 @@ def daily_frequencies_table daily_frequency?(obj) ? obj.frequency_date : obj[:date] end + unless @show_inactive_enrollments + @enrollment_classrooms= @enrollment_classrooms.uniq { |enrollment_classroom| enrollment_classroom[:student].id } + end + student_enrollment_ids ||= @enrollment_classrooms.map { |student_enrollment| student_enrollment[:student_enrollment].id } diff --git a/app/reports/attendance_record_report_by_student.rb b/app/reports/attendance_record_report_by_student.rb index 4ea00e314..98fa896fd 100644 --- a/app/reports/attendance_record_report_by_student.rb +++ b/app/reports/attendance_record_report_by_student.rb @@ -35,11 +35,13 @@ def initialize( end def call + calculated_frequencies = calculate_percentage_of_presence + classrooms.map do |classroom| students = enrollment_classrooms_list.select{ |student| student[:classroom_id].eql?(classroom.id) } - frequencies_by_classroom = calculate_percentage_of_presence.select do |student| + frequencies_by_classroom = calculated_frequencies.detect do |student| student[:classroom].eql?(classroom.id) - end.first + end next if frequencies_by_classroom.blank? || students.empty? @@ -52,11 +54,11 @@ def call student_id: student[:student_id], student_name: student[:student_name], sequence: student[:sequence], - frequency: frequencies_by_classroom[:students].select do |frequency_by_student| + frequency: frequencies_by_classroom[:students].detect do |frequency_by_student| if frequency_by_student[:student_id] == student[:student_id] frequency_by_student[:percentage_frequency] end - end.first + end } end } @@ -68,7 +70,7 @@ def call def query_daily_frequencies @daily_frequencies_by_classroom ||= DailyFrequencyQuery.call( - classroom_id: classrooms.map(&:id), + classroom_id: classrooms.pluck(:id), period: period, frequency_date: start_at..end_at, all_students_frequencies: true diff --git a/app/reports/exam_record_report.rb b/app/reports/exam_record_report.rb index 356dba194..0c66405d3 100644 --- a/app/reports/exam_record_report.rb +++ b/app/reports/exam_record_report.rb @@ -9,18 +9,54 @@ class ExamRecordReport < BaseReport # This factor represent the quantitty of students with social name needed to reduce 1 student by page SOCIAL_NAME_REDUCTION_FACTOR = 3 - def self.build(entity_configuration, teacher, year, school_calendar_step, test_setting, daily_notes, students_enrollments, complementary_exams, school_term_recoveries, recovery_lowest_notes, lowest_notes) - new(:landscape).build(entity_configuration, teacher, year, school_calendar_step, test_setting, daily_notes, students_enrollments, complementary_exams, school_term_recoveries, recovery_lowest_notes, lowest_notes) + def self.build( + entity_configuration, + teacher, + year, + school_calendar_step, + test_setting, + daily_notes, + info_students, + complementary_exams, + school_term_recoveries, + recovery_lowest_notes, + lowest_notes + ) + new(:landscape).build( + entity_configuration, + teacher, + year, + school_calendar_step, + test_setting, + daily_notes, + info_students, + complementary_exams, + school_term_recoveries, + recovery_lowest_notes, + lowest_notes + ) end - def build(entity_configuration, teacher, year, school_calendar_step, test_setting, daily_notes, students_enrollments, complementary_exams, school_term_recoveries, recovery_lowest_notes, lowest_notes) + def build( + entity_configuration, + teacher, + year, + school_calendar_step, + test_setting, + daily_notes, + info_students, + complementary_exams, + school_term_recoveries, + recovery_lowest_notes, + lowest_notes + ) @entity_configuration = entity_configuration @teacher = teacher @year = year @school_calendar_step = school_calendar_step @test_setting = test_setting @daily_notes = daily_notes - @students_enrollments = students_enrollments + @info_students = info_students @complementary_exams = complementary_exams @school_term_recoveries = school_term_recoveries @recovery_lowest_notes = recovery_lowest_notes @@ -40,20 +76,10 @@ def build(entity_configuration, teacher, year, school_calendar_step, test_settin private - def student_enrolled_on_date?(student_id, date) - student_list(date).include?(student_id) - end - - def student_list(date) - student_list ||= {} - student_list[date] ||= StudentEnrollmentsList.new( - classroom: classroom, - discipline: discipline, - date: date, - search_type: :by_date, - show_inactive: false - ).student_enrollments - .map(&:student_id) + def student_enrolled_on_date?(student_enrollment, date) + ActiveStudentsOnDate.call( + student_enrollments: student_enrollment, date: date + ) end def classroom @@ -105,62 +131,19 @@ def header end def daily_notes_table - averages = {} - recovery_lowest_note = {} school_term_recovery_scores = {} self.any_student_with_dependence = false - @students_enrollments.each do |student_enrollment| - averages[student_enrollment.id] = StudentAverageCalculator.new( - student_enrollment.student - ).calculate( - classroom, - discipline, - @school_calendar_step - ) - - if @lowest_notes - lowest_note = @lowest_notes[student_enrollment.student_id].to_s - - if lowest_note.present? - recovery_lowest_note[student_enrollment.id] = lowest_note - end - end - end - - exams = [] - integral_complementary_exams = [] - recoveries_avaliation_id = [] - recoveries_ids = [] - - @daily_notes.each do |daily_note| - exams << daily_note - if daily_note.avaliation.recovery_diary_record - exams << daily_note.avaliation.recovery_diary_record - recoveries_avaliation_id << daily_note.avaliation_id - recoveries_ids << daily_note.id - end - end + calculate_student_averages_and_recovery_notes + collect_exams_and_recoveries + collect_exams_and_complementary_exams @school_term_recoveries.each do |school_term_recovery| - exams << school_term_recovery - end - - @complementary_exams.each do |complementary_exam| - if complementary_exam.complementary_exam_setting.integral? - integral_complementary_exams << complementary_exam - next - end - - exams << complementary_exam + @exams << school_term_recovery end - integral_complementary_exams.each do |integral_exam| - exams << integral_exam - end - - exams.to_a - sliced_exams = exams.each_slice(10).to_a + @exams.to_a + sliced_exams = @exams.each_slice(10).to_a pos = 0 sliced_exams.each_with_index do |daily_notes_slice, index| @@ -168,9 +151,11 @@ def daily_notes_table students = {} daily_notes_slice.each do |exam| + student_enrollments_exempts = exempted_from_discipline?(exam) + if recovery_record(exam) - avaliation_id = recoveries_avaliation_id[pos] - daily_note_id = recoveries_ids[pos] + avaliation_id = @recoveries_avaliation_id[pos] + daily_note_id = @recoveries_ids[pos] pos += 1 elsif complementary_exam_record(exam) avaliation_id = nil @@ -182,23 +167,24 @@ def daily_notes_table avaliation_id = exam.avaliation_id daily_note_id = exam.id end + avaliations << make_cell(content: exam_description(exam), font_style: :bold, background_color: 'FFFFFF', align: :center, width: 55) - @students_enrollments.each do |student_enrollment| - student_id = student_enrollment.student_id - exempted_from_discipline = exempted_from_discipline?(student_enrollment, exam) + @info_students.each do |info_students| + student = info_students[:student] + student_enrollment = info_students[:student_enrollment] + exempted_from_discipline = student_enrollments_exempts[student_enrollment.id] in_active_search = ActiveSearch.new.in_active_search?(student_enrollment.id, exam.test_date) daily_note_student = nil - if exempted_from_discipline || (avaliation_id.present? && exempted_avaliation?(student_enrollment.student_id, avaliation_id)) + if exempted_from_discipline || (avaliation_id.present? && exempted_avaliation?(student.id, avaliation_id)) student_note = ExemptedDailyNoteStudent.new - averages[student_enrollment.id] = "D" if exempted_from_discipline + @averages[student_enrollment.id] = "D" if exempted_from_discipline elsif in_active_search @active_search = true - student_note = ActiveSearchDailyNoteStudent.new elsif avaliation_id.present? - note_student = DailyNoteStudent.find_by(student_id: student_id, daily_note_id: daily_note_id, active: true) + note_student = DailyNoteStudent.find_by(student_id: student.id, daily_note_id: daily_note_id, active: true) daily_note_student = student_transferred?(note_student) if note_student.present? student_note = daily_note_student || NullDailyNoteStudent.new end @@ -206,24 +192,18 @@ def daily_notes_table score = nil if exempted_from_discipline || avaliation_id.present? - averages[student_enrollment.id] = nil if exempted_from_discipline + @averages[student_enrollment.id] = nil if exempted_from_discipline - recovery_note = recovery_record(exam) ? exam.students.find_by_student_id(student_id).try(&:score) : nil - student_note.recovery_note = recovery_note if recovery_note.present? && daily_note_student.blank? - score = recovery_record(exam) ? student_note.recovery_note : student_note.note + score = set_student_score(exam, student, student_note, student_enrollment, daily_note_student) elsif complementary_exam_record(exam) - complementary_student = ComplementaryExamStudent.find_by(complementary_exam_id: exam.id, student_id: student_id) + complementary_student = ComplementaryExamStudent.find_by(complementary_exam_id: exam.id, student_id: student.id) score = complementary_student.present? ? complementary_student.try(:score) : NullDailyNoteStudent.new.note elsif school_term_recovery_record(exam) - recovery_student = RecoveryDiaryRecordStudent.find_by(student_id: student_id, recovery_diary_record_id: exam.recovery_diary_record_id) - - score = recovery_student.present? ? recovery_student.try(:score) : (student_enrolled_on_date?(student_id, exam.recorded_at) ? '' :NullDailyNoteStudent.new.note) - + recovery_student = RecoveryDiaryRecordStudent.find_by(student_id: student.id, recovery_diary_record_id: exam.recovery_diary_record_id) + score = recovery_student.present? ? recovery_student.try(:score) : (student_enrolled_on_date?(student_enrollment, exam.recorded_at) ? '' :NullDailyNoteStudent.new.note) school_term_recovery_scores[student_enrollment.id] = recovery_student.try(:score) end - student = Student.find(student_id) - 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 @@ -265,7 +245,7 @@ def daily_notes_table data_column_count = value[:scores].count + (value[:recoveries].nil? ? 0 : value[:recoveries].count) if @recovery_lowest_notes - student_cells << make_cell(content: "#{recovery_lowest_note[key]}", align: :center) + student_cells << make_cell(content: "#{@recovery_lowest_note[key]}", align: :center) end number_colums = 10 @@ -278,11 +258,11 @@ def daily_notes_table end recovery_average = SchoolTermAverageCalculator.new(classroom) - .calculate(averages[key], recovery_score) - averages[key] = ScoreRounder.new(classroom, RoundedAvaliations::SCHOOL_TERM_RECOVERY, @school_calendar_step) + .calculate(@averages[key], recovery_score) + @averages[key] = ScoreRounder.new(classroom, RoundedAvaliations::SCHOOL_TERM_RECOVERY, @school_calendar_step) .round(recovery_average) - average = averages[key] + average = @averages[key] student_cells << make_cell(content: "#{average}", font_style: :bold, align: :center) else student_cells << make_cell(content: '-', font_style: :bold, align: :center) @@ -310,7 +290,11 @@ def daily_notes_table data.concat(students_cells_slice) page_content do - table(data, row_colors: ['FFFFFF', 'DEDEDE'], cell_style: { size: 8, padding: [2, 2, 2, 2], inline_format: true }, width: bounds.width) do |t| + table(data, + row_colors: ['FFFFFF', 'DEDEDE'], + cell_style: { size: 8, padding: [2, 2, 2, 2], inline_format: true }, + width: bounds.width + ) do |t| t.cells.border_width = 0.25 t.before_rendering_page do |page| page.row(0).border_top_width = 0.25 @@ -328,6 +312,88 @@ def daily_notes_table end end + def set_student_score(exam, student, student_note, student_enrollment, daily_note_student) + recovery_note = find_recovery_note_if_needed(exam, student) + student_note.recovery_note = recovery_note if recovery_note.present? && daily_note_student.blank? + + determine_score(student_note, exam, student_enrollment) + end + + def find_recovery_note_if_needed(exam, student) + return nil unless recovery_record(exam) + + exam.students.find_by_student_id(student.id).try(&:score) + end + + def determine_score(student_note, exam, student_enrollment) + return student_note.note unless recovery_record(exam) + + recovery_score = student_note.recovery_note + + return recovery_score if student_enrolled_on_date?(student_enrollment, exam.recorded_at).present? + + NullDailyNoteStudent.new.note + end + + def calculate_student_averages_and_recovery_notes + @averages = {} + @recovery_lowest_note = {} + + @info_students.each do |info_students| + student = info_students[:student] + student_enrollment_id = info_students[:student_enrollment].id + + @averages[student_enrollment_id] = StudentAverageCalculator.new( + student + ).calculate( + classroom, + discipline, + @school_calendar_step + ) + + next if @lowest_notes.blank? + + lowest_note = @lowest_notes[student.id].to_s + + next if lowest_note.blank? + + @recovery_lowest_note[student_enrollment_id] = lowest_note + end + end + + def collect_exams_and_recoveries + @exams = [] + @recoveries_avaliation_id = [] + @recoveries_ids = [] + + @daily_notes.each do |daily_note| + @exams << daily_note + + next if daily_note.avaliation.recovery_diary_record.blank? + + @exams << daily_note.avaliation.recovery_diary_record + @recoveries_avaliation_id << daily_note.avaliation_id + @recoveries_ids << daily_note.id + end + end + + def collect_exams_and_complementary_exams + integral_complementary_exams = [] + + @complementary_exams.each do |complementary_exam| + if complementary_exam.complementary_exam_setting.integral? + integral_complementary_exams << complementary_exam + next + end + + @exams << complementary_exam + end + + integral_complementary_exams.each do |integral_exam| + @exams << integral_exam + end + end + def student_transferred?(note_student) return note_student unless note_student.transfer_note_id @@ -387,16 +453,16 @@ def exempted_avaliation?(student_id, avaliation_id) avaliation_is_exempted end - def exempted_from_discipline?(student_enrollment, exam) - discipline_id = exam.discipline.id - + def exempted_from_discipline?(exam) + steps_fetcher = StepsFetcher.new(classroom) test_date = exam.test_date - steps_fetcher = StepsFetcher.new(exam.classroom) step_number = steps_fetcher.step_by_date(test_date).to_number - student_enrollment.exempted_disciplines.by_discipline(discipline_id) - .by_step_number(step_number) - .any? + StudentsExemptFromDiscipline.call( + student_enrollments: @info_students.map { |info| info[:student_enrollment].id }, + discipline: discipline, + step: step_number + ) end def recovery_record(record) diff --git a/app/services/api/classroom_attendance_service.rb b/app/services/api/classroom_attendance_service.rb new file mode 100644 index 000000000..1aa13ba89 --- /dev/null +++ b/app/services/api/classroom_attendance_service.rb @@ -0,0 +1,172 @@ +module Api + class ClassroomAttendanceService + + attr_accessor :classrooms_api_code, :start_at, :end_at, :year + + def initialize(classrooms_api_code, start_at, end_at, year) + @classrooms_api_code = classrooms_api_code + @start_at = start_at + @end_at = end_at + @year = year + end + + def self.call(classrooms_api_code, start_at, end_at, year) + new(classrooms_api_code, start_at, end_at, year).call + end + + def call + enrollment_classrooms = query_student_enrollment_classrooms + daily_frequencies = query_daily_frequencies + + build_classroom_information(enrollment_classrooms, daily_frequencies) + end + + private + + def classrooms + @classrooms ||= Classroom + .includes(classrooms_grades: { grade: :course }) + .where(api_code: classrooms_api_code.values) + .by_year(year) + .order(:api_code) + end + + def query_student_enrollment_classrooms + enrollment_classrooms = StudentEnrollmentClassroom + .includes(student_enrollment: :student) + .by_classroom(classrooms_ids) + .by_date_range(start_at, end_at) + .group_by(&:classroom_code) + + organize_enrollment_classrooms(enrollment_classrooms) + end + + def organize_enrollment_classrooms(enrollment_classrooms) + counts = {} + days = school_days.pluck(:school_day).map(&:to_s) + + enrollment_classrooms.each do |classroom_code, enrollments| + counts[classroom_code] ||= {} + + days.each do |day| + counts[classroom_code][day] ||= { enrollments: 0 } + + enrollments.each do |enrollment| + next unless enrollment.joined_at <= day && (enrollment.left_at.blank? || enrollment.left_at >= day) + + counts[classroom_code][day][:enrollments] += 1 + end + end + end + + counts + end + + def query_daily_frequencies + school_days_query = school_days.select(:school_day).to_sql + + daily_frequencies_query = DailyFrequency.select(:id, :frequency_date, :classroom_id) + .where(classroom_id: classrooms_ids) + .to_sql + + sanitized_sql = <<-SQL.squish + SELECT + COUNT(DISTINCT CONCAT(dfs.student_id::TEXT, '-', df.frequency_date::TEXT)) AS count, + COUNT(DISTINCT CASE + WHEN dfs.present and sec.id is not null + THEN dfs.student_id::TEXT || '-' || df.frequency_date::TEXT + END) AS presences, + c.api_code AS classroom_api_code, + df.frequency_date AS frequency_date + FROM + (#{school_days_query}) AS sd + LEFT JOIN + (#{daily_frequencies_query}) AS df ON df.frequency_date = sd.school_day + LEFT JOIN + classrooms c ON c.id = df.classroom_id AND c.discarded_at IS NULL + LEFT JOIN + daily_frequency_students dfs ON dfs.daily_frequency_id = df.id AND dfs.discarded_at IS NULL + LEFT JOIN + students s ON s.id = dfs.student_id AND s.discarded_at IS NULL + LEFT JOIN + student_enrollments se ON se.student_id = s.id AND se.discarded_at IS NULL + LEFT JOIN + student_enrollment_classrooms sec ON sec.student_enrollment_id = se.id AND sec.discarded_at IS NULL + WHERE + sec.joined_at::DATE <= sd.school_day and (sec.left_at = '' or sec.left_at::DATE >= sd.school_day) + and sec.classroom_code = c.api_code + GROUP BY + c.api_code, df.frequency_date + SQL + + query = ActiveRecord::Base.connection.exec_query(sanitized_sql) + + organize_daily_frequencies(query) + end + + def organize_daily_frequencies(frequencies) + frequencies.each_with_object({}) do |record, hash| + classroom_api_code = record['classroom_api_code'] + frequency_date = record['frequency_date'] + presences = record['presences'] + + hash[classroom_api_code] ||= {} + hash[classroom_api_code][frequency_date] = presences + end + end + + def build_classroom_information(student_enrollment_classrooms, daily_frequencies) + @classrooms.map do |classroom| + classroom_api_code = classroom.api_code + classroom_name = classroom.description + classroom_max_students = classroom.max_students + enrollments_by_classroom = student_enrollment_classrooms[classroom_api_code] ||= {} + frequencies_by_classroom = daily_frequencies[classroom_api_code] ||= {} + + frequencies_with_enrollments = merge_frequencies_with_enrollments(frequencies_by_classroom, +enrollments_by_classroom) + + grades = build_grade_hashes(classroom) + + { + classroom_id: classroom_api_code, + classroom_name: classroom_name, + classroom_max_students: classroom_max_students, + grades: grades, + attendance_and_enrollments: frequencies_with_enrollments + } + end + end + + def build_grade_hashes(classroom) + classroom.classrooms_grades.map do |classroom_grade| + { + id: classroom_grade.grade.api_code, + name: classroom_grade.grade.description, + course_id: classroom_grade.grade.course.api_code, + course_name: classroom_grade.grade.course.description + } + end + end + + def merge_frequencies_with_enrollments(frequencies_by_classroom, enrollments_by_classroom) + enrollments_by_classroom.map do |date_enrollments, enrollments_count| + { + date_enrollments => { + frequencies: frequencies_by_classroom[date_enrollments] || 0, + enrollments: enrollments_count[:enrollments] + } + } + end.reduce(:merge) + end + + def school_days + @school_days ||= UnitySchoolDay.where(unity_id: @classrooms.first.unity_id) + .where('school_day BETWEEN ? AND ?', start_at, end_at) + end + + def classrooms_ids + @classrooms_ids ||= classrooms.pluck(:id) + end + end +end diff --git a/app/services/api/list_student_attendances_by_classroom_service.rb b/app/services/api/list_student_attendances_by_classroom_service.rb new file mode 100644 index 000000000..b914406d2 --- /dev/null +++ b/app/services/api/list_student_attendances_by_classroom_service.rb @@ -0,0 +1,99 @@ +module Api + class ListStudentAttendancesByClassroomService + attr_accessor :classroom_api_code, :start_at, :end_at, :year, :students_api_code + + def initialize(classroom_api_code, start_at, end_at, year, students_api_code) + @classroom_api_code = classroom_api_code + @start_at = start_at + @end_at = end_at + @year = year + @students_api_code = students_api_code + end + + def self.call(classroom_api_code, start_at, end_at, year, students_api_code) + new(classroom_api_code, start_at, end_at, year, students_api_code).call + end + + def call + classroom = query_classroom + enrollment_details = query_student_enrollment_classrooms.to_h + frequencies_by_classrooms = process_daily_frequencies_by_classroom(classroom, enrollment_details) + + build_classroom_information(classroom, frequencies_by_classrooms) + end + + private + + def query_classroom + Classroom.includes(classrooms_grades: { grade: :course }).find_by(year: year, api_code: classroom_api_code) + end + + def query_student_enrollment_classrooms + StudentEnrollmentClassroom.joins(student_enrollment: :student) + .where( + students: { api_code: students_api_code.values }, + classroom_code: classroom_api_code + ) + .pluck('students.api_code', :joined_at) + end + + def process_daily_frequencies_by_classroom(classroom, enrollment_details) + student_ids = Student.where(api_code: students_api_code.values).pluck(:id) + daily_frequencies = query_daily_frequencies(classroom.id, student_ids) + + format_frequencies(daily_frequencies, enrollment_details) + end + + def query_daily_frequencies(classroom_id, student_ids) + DailyFrequency + .by_classroom_id(classroom_id) + .by_frequency_date_between(start_at, end_at) + .joins(:classroom, students: :student) + .where(daily_frequency_students: { student_id: student_ids }) + .group('classrooms.api_code, students.api_code, students.name') + .select(" + students.api_code AS student_api_code, + students.name AS student_name, + SUM(daily_frequency_students.present::int) AS presences, + SUM((NOT daily_frequency_students.present)::int) AS absences, + classrooms.api_code AS classroom_api_code + ") + .order("UPPER(students.name)") + end + + def format_frequencies(daily_frequencies, enrollment_details) + daily_frequencies.each_with_object({}) do |record, hash| + classroom_code = record['classroom_api_code'] + student_code = record['student_api_code'] + + hash[classroom_api_code] ||= {} + hash[classroom_api_code][student_code] ||= { + name: record['student_name'], + presences: record['presences'], + absences: record['absences'], + joined_at: enrollment_details[student_code] + } + end + end + + def build_classroom_information(classroom, daily_frequencies) + { + classroom_id: classroom.api_code, + classroom_name: classroom.description, + grades: build_grades(classroom), + attendances_by_student: daily_frequencies[classroom_api_code] || {} + } + end + + def build_grades(classroom) + classroom.classrooms_grades.map do |classroom_grade| + { + id: classroom_grade.grade_id, + name: classroom_grade.grade.description, + course_id: classroom_grade.grade.course_id, + course_name: classroom_grade.grade.course.description + } + end + end + end +end diff --git a/app/services/daily_note_creator.rb b/app/services/daily_note_creator.rb deleted file mode 100644 index 56c4e7108..000000000 --- a/app/services/daily_note_creator.rb +++ /dev/null @@ -1,44 +0,0 @@ -class DailyNoteCreator - attr_reader :daily_note - - def initialize(params) - @params = params - end - - def self.find_or_create(params) - new(params).find_or_create - end - - def find_or_create - @daily_note = DailyNote.find_or_initialize_by(@params) - - if @daily_note.new_record? - student_enrollments = fetch_student_enrollments || [] - student_ids = student_enrollments.map(&:student_id).uniq - student_ids.each do |student_id| - if student = Student.find_by_id(student_id) - @daily_note.students.build(student_id: student.id, daily_note: @daily_note, active: true) - end - end - - @daily_note.save - else - true - end - end - - private - - def fetch_student_enrollments - return if @daily_note.avaliation.nil? - - @student_enrollments ||= StudentEnrollmentsList.new( - classroom: @daily_note.classroom, - grade: @daily_note.avaliation.grade_ids, - discipline: @daily_note.discipline, - date: @daily_note.avaliation.test_date, - score_type: StudentEnrollmentScoreTypeFilters::NUMERIC, - search_type: :by_date - ).student_enrollments - end -end diff --git a/app/services/delete_dispensed_exams_and_frequencies_service.rb b/app/services/delete_dispensed_exams_and_frequencies_service.rb index 211f168e1..f8e87daf2 100644 --- a/app/services/delete_dispensed_exams_and_frequencies_service.rb +++ b/app/services/delete_dispensed_exams_and_frequencies_service.rb @@ -32,12 +32,15 @@ def remove_dispensed_exams_and_frequencies(student_enrollment) end_date = step.end_at student_id = student_enrollment.student_id classroom_id = classroom.id - - destroy_invalid_daily_note_students(student_id, classroom_id, start_date, end_date) - destroy_invalid_recovery_diary_record_students(student_id, classroom_id, start_date, end_date) - destroy_invalid_conceptual_exams(student_id, classroom_id, step_number) - destroy_invalid_descriptive_exams(student_id, classroom_id, step_number) - destroy_invalid_daily_frequency_students(student_id, classroom_id, start_date, end_date) + user_admin = User.find_by(admin: true) + + Audited.audit_class.as_user(user_admin) do + destroy_invalid_daily_note_students(student_id, classroom_id, start_date, end_date) + destroy_invalid_recovery_diary_record_students(student_id, classroom_id, start_date, end_date) + destroy_invalid_conceptual_exams(student_id, classroom_id, step_number) + destroy_invalid_descriptive_exams(student_id, classroom_id, step_number) + destroy_invalid_daily_frequency_students(student_id, classroom_id, start_date, end_date) + end end end end diff --git a/app/services/exam_poster/conceptual_exam_poster.rb b/app/services/exam_poster/conceptual_exam_poster.rb index c9a485f6a..1825bb20e 100644 --- a/app/services/exam_poster/conceptual_exam_poster.rb +++ b/app/services/exam_poster/conceptual_exam_poster.rb @@ -34,24 +34,28 @@ def post_conceptual_exams classrooms.each do |classroom| next unless can_post?(classroom) + step = get_step(classroom) + conceptual_exams = ConceptualExam.joins(:student) + .by_classroom(classroom) + .by_unity(step.school_calendar.unity) + .by_step_id(classroom, step.id) - conceptual_exam_ids = ConceptualExam.joins(:student) - .by_classroom(classroom) - .by_unity(get_step(classroom).school_calendar.unity) - .by_step_id(classroom, get_step(classroom).id) - .pluck(:id) - exempted_discipline_ids = - ExemptedDisciplinesInStep.discipline_ids(classroom.id, get_step(classroom).to_number) + student_ids, conceptual_exams_ids = conceptual_exams.pluck(:student_id, :id).transpose + exempted_disciplines = exempt_discipline_students(classroom, discipline_ids, student_ids, step.to_number) + exempted_discipline_ids = ExemptedDisciplinesInStep.discipline_ids(classroom.id, step.to_number) conceptual_exam_values = ConceptualExamValue.active .includes(:conceptual_exam, :discipline) - .where(conceptual_exam_id: conceptual_exam_ids) + .where(conceptual_exam_id: conceptual_exams_ids) .where.not(discipline_id: exempted_discipline_ids) .where(discipline_id: discipline_ids) .distinct conceptual_exam_values.each do |conceptual_exam_value| conceptual_exam = conceptual_exam_value.conceptual_exam + discipline_id = conceptual_exam_value.discipline_id + next if exempted_disciplines[conceptual_exam.student_id].present? && + exempted_disciplines[conceptual_exam.student_id].pluck(:discipline_id).include?(discipline_id) next unless not_posted?({ classroom: classroom, student: conceptual_exam.student, discipline: conceptual_exam_value.discipline })[:conceptual_exam] if conceptual_exam_value.value.blank? @@ -72,5 +76,18 @@ def post_conceptual_exams params end + + def exempt_discipline_students(classroom, discipline_ids, student_ids, step_number) + StudentEnrollmentExemptedDiscipline.includes(student_enrollment: :student) + .joins(student_enrollment: + [ + :student, student_enrollment_classrooms: + [classrooms_grade: :classroom] + ]) + .where(classrooms_grades: { classroom_id: classroom.id }) + .where(students: { id: student_ids }, discipline_id: discipline_ids) + .by_step_number(step_number) + .group_by { |exempt| exempt.student_enrollment.student_id } + end end end diff --git a/app/services/exam_poster/numerical_exam_poster.rb b/app/services/exam_poster/numerical_exam_poster.rb index 13d7b11ad..5e2dc39f8 100644 --- a/app/services/exam_poster/numerical_exam_poster.rb +++ b/app/services/exam_poster/numerical_exam_poster.rb @@ -119,25 +119,22 @@ def post_by_classrooms end def fetch_exam_rules(classroom, students) - enrollment_classrooms = StudentEnrollmentClassroom.includes( - student_enrollment: :student, - classrooms_grade: :exam_rule - ).by_student(students).by_classroom(classroom).by_date(Date.current) - classrooms_grades = classroom.classrooms_grades.where( - id: enrollment_classrooms.map(&:classrooms_grade).uniq - ).first - - return {} if classrooms_grades.nil? + enrollment_classrooms = StudentEnrollmentClassroom + .includes(student_enrollment: :student, classrooms_grade: :exam_rule) + .by_student(students) + .by_classroom(classroom) + .by_date(Date.current) enrollment_classrooms_exam_rules = {} enrollment_classrooms.each do |sec| student_id = sec.student_enrollment.student_id + exam_rule = sec.classrooms_grade.exam_rule next if enrollment_classrooms_exam_rules.key?(student_id) enrollment_classrooms_exam_rules[sec.student_id] = { - exam_rule: classrooms_grades.exam_rule + exam_rule: exam_rule } end diff --git a/app/services/ieducar_synchronizers/classrooms_synchronizer.rb b/app/services/ieducar_synchronizers/classrooms_synchronizer.rb index c9fff2ef8..3a263a944 100644 --- a/app/services/ieducar_synchronizers/classrooms_synchronizer.rb +++ b/app/services/ieducar_synchronizers/classrooms_synchronizer.rb @@ -40,6 +40,7 @@ def update_classrooms(classrooms) classroom.unity_code = classroom_record.escola_id classroom.period = classroom_record.turno_id classroom.year = classroom_record.ano + classroom.max_students = classroom_record.max_aluno if classroom.persisted? && classroom.period_changed? && classroom.period_was.present? update_period_dependents(classroom.id, classroom.period_was, classroom.period) diff --git a/app/services/ieducar_synchronizers/exam_rules_synchronizer.rb b/app/services/ieducar_synchronizers/exam_rules_synchronizer.rb index a7a7e80ae..e8285ee0d 100644 --- a/app/services/ieducar_synchronizers/exam_rules_synchronizer.rb +++ b/app/services/ieducar_synchronizers/exam_rules_synchronizer.rb @@ -64,13 +64,16 @@ def update_differentiated_exam_rules(differentiated_exam_rules) def update_descriptive_exams(exam_rule) return unless exam_rule.attribute_changed?("opinion_type") + user_admin = User.find_by(admin: true) classroom_ids = ClassroomsGrade.where(exam_rule_id: exam_rule.id) .pluck(:classroom_id) .uniq - DescriptiveExam.where(classroom_id: classroom_ids) - .where.not(opinion_type: exam_rule.opinion_type) - .destroy_all - DescriptiveExamStudent.by_classroom(classroom_ids).destroy_all + Audited.audit_class.as_user(user_admin) do + DescriptiveExam.where(classroom_id: classroom_ids) + .where.not(opinion_type: exam_rule.opinion_type) + .destroy_all + DescriptiveExamStudent.by_classroom(classroom_ids).discard_all + end end end diff --git a/app/services/infrequency_tracking_notifier.rb b/app/services/infrequency_tracking_notifier.rb index bfde5df1a..804d35dfb 100644 --- a/app/services/infrequency_tracking_notifier.rb +++ b/app/services/infrequency_tracking_notifier.rb @@ -51,7 +51,7 @@ def students_with_absences_query(start_at = nil) end def classrooms_with_absences - students_with_absences_query.map(&:classroom).compact.uniq + @students_with_absences ||= students_with_absences_query.map(&:classroom).compact.uniq end def students_with_absences(classroom_id, start_at) @@ -71,11 +71,9 @@ def school_dates(end_at, classroom) school_dates = [] classroom.grade_ids.each do |grade| - school_dates << SchoolDayChecker.new( - school_calendar(classroom), end_at, grade, classroom.id, nil - ).school_dates_since( - end_at, days - ).sort + school_dates << SchoolDayChecker.new(school_calendar(classroom), end_at, grade, classroom.id, nil) + .school_dates_since(end_at, days) + .sort end school_dates.flatten @@ -143,13 +141,13 @@ def description_by_type(infrequency_tracking, type) end def users_to_notify(unity_id = nil) - role_ids = RolePermission.where( - feature: :infrequency_trackings, - permission: :change - ).pluck(:role_id) - user_roles = UserRole.where(role_id: role_ids) - user_roles = user_roles.where('(unity_id IS NULL OR unity_id = ?)', unity_id) if unity_id.present? - User.joins(:user_roles).merge(user_roles) + User.joins(:user_roles) + .where(user_roles: { + role_id: RolePermission + .where(feature: :infrequency_trackings, permission: :change) + .select(:role_id) + }) + .where('user_roles.unity_id IS NULL OR user_roles.unity_id = ?', unity_id) end def need_send_notification?(type, school_dates, absence_dates) diff --git a/app/services/remove_daily_note_students.rb b/app/services/remove_daily_note_students.rb index e6f4343bf..45fc6c274 100644 --- a/app/services/remove_daily_note_students.rb +++ b/app/services/remove_daily_note_students.rb @@ -14,7 +14,11 @@ def initialize(joined_at, left_at, student_id, classroom_id) def call avaliations = Avaliation.by_classroom_id(classroom_id).pluck(:id, :test_date).to_h daily_note_ids = DailyNote.where(avaliation_id: avaliations.keys).pluck(:id) - daily_note_students = DailyNoteStudent.with_discarded.where(daily_note_id: daily_note_ids, student_id: student_id) + daily_note_students = DailyNoteStudent.with_discarded + .where( + daily_note_id: daily_note_ids, + student_id: student_id + ) daily_note_students.each do |daily_note_student| avaliation_id = daily_note_student.daily_note.avaliation_id @@ -22,13 +26,18 @@ def call next if daily_note_student.note.present? || daily_note_student.transfer_note_id.present? - daily_note_student.discard_or_undiscard(student_inactive_in_date?) - daily_note_student.active = !student_inactive_in_date? + if student_inactive_in_date? + daily_note_student.discard + daily_note_student.active = false + else + daily_note_student.undiscard + daily_note_student.active = true + end end end def student_inactive_in_date? - @date_avaliation < joined_at.to_date && @date_avaliation >= left_at.to_date + @date_avaliation < joined_at.to_date || @date_avaliation >= left_at.to_date end private diff --git a/app/services/school_day_checker.rb b/app/services/school_day_checker.rb index 759feb1e4..b2c388570 100644 --- a/app/services/school_day_checker.rb +++ b/app/services/school_day_checker.rb @@ -49,16 +49,6 @@ def destroy(events) end end - def next_school_day - date = @date - - while not date_is_school_day?(date) - date = date.next_day - end - - date - end - def school_dates_between(start_date, end_date) start_date.upto(end_date).select do |current_date| date_is_school_day?(current_date) diff --git a/app/services/student_enrollment_classrooms_retriever.rb b/app/services/student_enrollment_classrooms_retriever.rb index 325fe3d36..0019892dc 100644 --- a/app/services/student_enrollment_classrooms_retriever.rb +++ b/app/services/student_enrollment_classrooms_retriever.rb @@ -2,6 +2,13 @@ class StudentEnrollmentClassroomsRetriever SEARCH_TYPES = [ :by_date, :by_date_range, :by_year ].freeze + ERROR_MESSAGES = { + missing_date: 'Should define date argument on search by date', + missing_date_range: 'Should define start_at or end_at argument on search by date_range', + missing_year: 'Should define year argument on search by year', + invalid_search_type: 'Invalid search type' + }.freeze + def self.call(params) new(params).call @@ -15,12 +22,13 @@ def initialize(params) @start_at = params.fetch(:start_at, nil) @end_at = params.fetch(:end_at, nil) @year = params.fetch(:year, nil) - @grade = params.fetch(:grade, nil) + @grades = params.fetch(:grades, nil) @include_date_range = params.fetch(:include_date_range, nil) @period = params.fetch(:period, nil) @opinion_type = params.fetch(:opinion_type, nil) @with_recovery_note_in_step = params.fetch(:with_recovery_note_in_step, nil) @score_type = params.fetch(:score_type, StudentEnrollmentScoreTypeFilters::BOTH) + @include_inactive = params.fetch(:include_inactive, true) ensure_has_valid_search_params end @@ -37,15 +45,19 @@ def call .active enrollment_classrooms = enrollment_classrooms.by_discipline(disciplines) if disciplines.present? - enrollment_classrooms = enrollment_classrooms.by_grade(grade) if grade + enrollment_classrooms = enrollment_classrooms.by_grade(grades) if grades enrollment_classrooms = enrollment_classrooms.by_period(period) if period - enrollment_classrooms = enrollment_classrooms.with_recovery_note_in_step(step, discipline) if with_recovery_note_in_step + + if with_recovery_note_in_step + enrollment_classrooms = enrollment_classrooms.with_recovery_note_in_step(step,discipline) + end + enrollment_classrooms = enrollment_classrooms.by_opinion_type(opinion_type, classrooms) if opinion_type enrollment_classrooms = search_by_dates(enrollment_classrooms) if include_date_range if enrollment_classrooms.show_as_inactive.blank? - enrollment_classrooms = search_by_search_type(enrollment_classrooms) + enrollment_classrooms = filter_by_type(enrollment_classrooms) enrollment_classrooms = reject_duplicated_students(enrollment_classrooms) end @@ -60,16 +72,18 @@ def call private - attr_accessor :classrooms, :disciplines, :year, :date, :start_at, :end_at, :search_type, - :include_date_range, :grade, :period, :opinion_type, :with_recovery_note_in_step, :score_type + attr_accessor :classrooms, :disciplines, :year, :date, :start_at, :end_at, :search_type, :include_inactive, + :include_date_range, :grades, :period, :opinion_type, :with_recovery_note_in_step, :score_type def ensure_has_valid_search_params if search_type.eql?(:by_date) - raise ArgumentError, 'Should define date argument on search by date' unless date + raise ArgumentError, ERROR_MESSAGES[:missing_date] unless date elsif search_type.eql?(:by_date_range) - raise ArgumentError, 'Should define start_at or end_at argument on search by date_range' unless start_at || end_at + raise ArgumentError, ERROR_MESSAGES[:missing_date_range] unless start_at || end_at elsif search_type.eql?(:by_year) - raise ArgumentError, 'Should define start_at or end_at argument on search by date_range' unless year + raise ArgumentError, ERROR_MESSAGES[:missing_year] unless year + else + raise ArgumentError, ERROR_MESSAGES[:invalid_search_type] end end @@ -81,7 +95,7 @@ def search_by_dates(enrollment_classrooms) enrollment_in_date end - def search_by_search_type(enrollment_classrooms) + def filter_by_type(enrollment_classrooms) return enrollment_classrooms if include_date_range.present? || show_inactive_enrollments if search_type.eql?(:by_date) @@ -98,12 +112,20 @@ def search_by_search_type(enrollment_classrooms) def reject_duplicated_students(enrollment_classrooms) return enrollment_classrooms if show_inactive_enrollments - last_student_classroom = enrollment_classrooms.select do |ec| - ec.left_at.blank? || ec.left_at.to_date.between?(start_at.to_date, end_at.to_date) + enrollment_classrooms.select do |ec| + if search_type.eql?(:by_date_range) + ec.left_at.blank? || (ec.joined_at.to_date <= end_at.to_date && ec.left_at.to_date >= start_at.to_date) + elsif search_type.eql?(:by_date) + ec.left_at.blank? || date.to_date <= ec.left_at.to_date + elsif search_type.eql?(:by_year) + ec.left_at.blank? || year == ec.left_at.to_date.year + end end end def show_inactive_enrollments + return false unless include_inactive + @show_inactive_enrollments ||= GeneralConfiguration.first.show_inactive_enrollments end end diff --git a/app/services/students_in_recovery_fetcher.rb b/app/services/students_in_recovery_fetcher.rb index 09ea553e2..200f8f871 100644 --- a/app/services/students_in_recovery_fetcher.rb +++ b/app/services/students_in_recovery_fetcher.rb @@ -16,12 +16,13 @@ def initialize(ieducar_api_configuration, classroom_id, discipline_id, step_id, def fetch @students = [] - if (classroom_grades_with_recovery_rule.first.exam_rule.differentiated_exam_rule.blank? || - classroom_grades_with_recovery_rule.first.exam_rule.differentiated_exam_rule.recovery_type == classroom_grades_with_recovery_rule.first.exam_rule.recovery_type) - @students += fetch_by_recovery_type(classroom_grades_with_recovery_rule.first.exam_rule.recovery_type) + recovery_type = exam_rule.recovery_type + + if (exam_rule.differentiated_exam_rule.blank? || exam_rule.differentiated_exam_rule.recovery_type == recovery_type) + @students += fetch_by_recovery_type(recovery_type) else - @students += fetch_by_recovery_type(classroom_grades_with_recovery_rule.first.exam_rule.recovery_type, false) - @students += fetch_by_recovery_type(classroom_grades_with_recovery_rule.first.exam_rule.differentiated_exam_rule.recovery_type, true) + @students += fetch_by_recovery_type(recovery_type, false) + @students += fetch_by_recovery_type(exam_rule.differentiated_exam_rule.recovery_type, true) end @students.uniq! @@ -32,77 +33,19 @@ def fetch private def fetch_by_recovery_type(recovery_type, differentiated = nil) - case recovery_type - when RecoveryTypes::PARALLEL - students = fetch_students_in_parallel_recovery(differentiated) - when RecoveryTypes::SPECIFIC - students = fetch_students_in_specific_recovery(differentiated) - else - students = [] - end - - students - end - - def classroom - @classroom ||= Classroom.find(@classroom_id) - end - - def classroom_grades_with_recovery_rule - return @classroom_grade if @classroom_grade.present? - - @classroom_grade = [] - - classroom_grades&.each { |classroom_grade| @classroom_grade << classroom_grade unless classroom_grade.exam_rule.recovery_type.eql?(0) } + return fetch_students_in_parallel_recovery(differentiated) if recovery_type.eql?(RecoveryTypes::PARALLEL) + return fetch_students_in_specific_recovery(differentiated) if recovery_type.eql?(RecoveryTypes::SPECIFIC) - if @classroom_grade.empty? - classroom_grades - else - @classroom_grade - end - end - - def classroom_grades - classroom.classrooms_grades.includes(:exam_rule) - end - - def discipline - @discipline ||= Discipline.find(@discipline_id) - end - - def steps_fetcher - @steps_fetcher ||= StepsFetcher.new(classroom) - end - - def step - @step ||= steps_fetcher.step_by_id(@step_id) - end - - def student_enrollments(classroom_grade_ids) - end_at = @date.to_date > step.end_at ? step.end_at : @date.to_date - - @student_enrollments ||= fetch_student_enrollments(end_at, classroom_grade_ids, discipline, step, classroom) - end - - def fetch_student_enrollments(end_at, classroom_grade_ids, discipline, step, classroom) - enrollment_classrooms_list = StudentEnrollmentClassroomsRetriever.call( - classrooms: classroom, - disciplines: discipline, - start_at: step.start_at, - end_at: end_at, - classroom_grades: classroom_grade_ids, - search_type: :by_date_range - ) - enrollment_classrooms_list.map{ |ec| ec[:student_enrollment]} + [] end def fetch_students_in_parallel_recovery(differentiated = nil) students = filter_students_in_recovery - if classroom_grades_with_recovery_rule.first.exam_rule.parallel_recovery_average + if exam_rule.parallel_recovery_average students = students.select do |student| - average = student.average(classroom, discipline, step) || 0 - average < classroom_grades_with_recovery_rule.first.exam_rule.parallel_recovery_average + average = student[:student].average(classroom, discipline, step) || 0 + average < exam_rule.parallel_recovery_average end end @@ -111,34 +54,26 @@ def fetch_students_in_parallel_recovery(differentiated = nil) def filter_students_in_recovery classroom_grade_ids = classroom_grades_with_recovery_rule.map(&:id) - student_enrollments_in_recovery = student_enrollments(classroom_grade_ids) - - student_enrollments_in_recovery.map(&:student) + fetch_student_enrollment_classroooms(classroom_grade_ids) end def fetch_students_in_specific_recovery(differentiated = nil) students = [] recovery_steps = RecoveryStepsFetcher.new(step, classroom).fetch - - recovery_exam_rule = classroom_grades_with_recovery_rule.first.exam_rule.recovery_exam_rules.find { |recovery_diary_record| + recovery_exam_rule = exam_rule.recovery_exam_rules.find { |recovery_diary_record| recovery_diary_record.steps.last.eql?(@step.to_number) } if recovery_exam_rule.present? - students = filter_students_in_recovery.select { |student| - sum_averages = 0 - - recovery_steps.each do |step| - next unless (average = student.average(classroom, discipline, step)) - - sum_averages += average + students = filter_students_in_recovery.select do |student| + sum_averages = recovery_steps.sum do |step| + student[:student].average(classroom, discipline, step) || 0 end - - average = sum_averages / recovery_steps.count + average = sum_averages / recovery_steps.count.to_f average < recovery_exam_rule.average - } + end end filter_differentiated_students(students, differentiated) @@ -147,10 +82,58 @@ def fetch_students_in_specific_recovery(differentiated = nil) def filter_differentiated_students(students, differentiated) if differentiated == !!differentiated students = students.select do |student| + student = student[:student] if student[:student].present? student.uses_differentiated_exam_rule == differentiated end end students end + + def fetch_student_enrollment_classroooms(classroom_grade_ids) + @student_enrollment_classroooms ||= StudentEnrollmentClassroomsRetriever.call( + classrooms: classroom, + disciplines: discipline, + date: @date, + classroom_grades: classroom_grade_ids, + search_type: :by_date + ) + end + + def classroom_grades_with_recovery_rule + return @classroom_grade if @classroom_grade.present? + + @classroom_grade = [] + + classroom_grades&.each do |classroom_grade| + @classroom_grade << classroom_grade unless classroom_grade.exam_rule.recovery_type.eql?(0) + end + + @classroom_grade = classroom_grades if @classroom_grade.empty? + @classroom_grade + end + + def classroom_grades + classroom.classrooms_grades.includes(:exam_rule) + end + + def discipline + @discipline ||= Discipline.find(@discipline_id) + end + + def steps_fetcher + @steps_fetcher ||= StepsFetcher.new(classroom) + end + + def step + @step ||= steps_fetcher.step_by_id(@step_id) + end + + def exam_rule + @exam_rule ||= classroom_grades_with_recovery_rule.first.exam_rule + end + + def classroom + @classroom ||= Classroom.find(@classroom_id) + end end diff --git a/app/services/teacher_period_fetcher.rb b/app/services/teacher_period_fetcher.rb index 39b1d441f..20255eef4 100644 --- a/app/services/teacher_period_fetcher.rb +++ b/app/services/teacher_period_fetcher.rb @@ -24,6 +24,6 @@ def teacher_period end def classroom_period - @classroom_period ||= Classroom.find(@classroom_id).period.to_i + @classroom_period ||= Classroom.find_by(id: @classroom_id)&.period.to_i end end diff --git a/app/services/teacher_work_done_chart_fetcher.rb b/app/services/teacher_work_done_chart_fetcher.rb index bf8da6ef9..c315e8e23 100644 --- a/app/services/teacher_work_done_chart_fetcher.rb +++ b/app/services/teacher_work_done_chart_fetcher.rb @@ -9,7 +9,8 @@ def initialize(params) def fetch! return { pending_notes_count: 0, completed_notes_count: 0 } if classroom.blank? || discipline.blank? - teacher_avaliations = Avaliation.by_classroom_id(classroom) + teacher_avaliations = Avaliation.includes(daily_notes: :students) + .by_classroom_id(classroom) .by_discipline_id(discipline) if classroom.calendar @@ -18,39 +19,20 @@ def fetch! teacher_avaliations = teacher_avaliations.by_school_calendar_step(school_calendar_step) end - completed_daily_note_students_count = 0 - all_daily_note_students_count = 0 - - teacher_avaliations.each do |avaliation| - students = StudentEnrollmentsList.new( - classroom: classroom, - discipline: discipline, - date: avaliation.test_date, - show_inactive: false, - score_type: StudentEnrollmentScoreTypeFilters::NUMERIC, - search_type: :by_date - ).student_enrollments - all_daily_note_students_count += students.count - all_daily_note_students_count -= AvaliationExemption.by_avaliation(avaliation.id).count - - completed_daily_note_students = DailyNoteStudent.by_avaliation(avaliation.id) - .by_student_id(students.map(&:student_id)) - .where(active: true) - .where.not(note: nil) - .reject(&:exempted?) - completed_daily_note_students_count += completed_daily_note_students.count + all_daily_notes = teacher_avaliations.flat_map(&:daily_notes) + completed_daily_note_count = all_daily_notes.count do |daily_note| + daily_note.status == DailyNoteStatuses::COMPLETE end - pending_notes_count = all_daily_note_students_count - completed_daily_note_students_count + pending_notes_count = all_daily_notes.size - completed_daily_note_count { pending_notes_count: pending_notes_count, - completed_notes_count: completed_daily_note_students_count + completed_notes_count: completed_daily_note_count } end private attr_accessor :teacher, :classroom, :discipline, :school_calendar_step - end diff --git a/app/services/unique_daily_frequency_students_creator.rb b/app/services/unique_daily_frequency_students_creator.rb index 49d8f6da1..5a6f5990f 100644 --- a/app/services/unique_daily_frequency_students_creator.rb +++ b/app/services/unique_daily_frequency_students_creator.rb @@ -18,37 +18,46 @@ def call_worker(entity_id, classroom_id, frequency_date, teacher_id) end def create!(classroom_id, frequency_date, teacher_id) - daily_frequency_students = {} - daily_frequencies = DailyFrequency.by_classroom_id(classroom_id) - .by_frequency_date(frequency_date) - .by_teacher_discipline_classroom(teacher_id, classroom_id) - - if daily_frequencies.present? - daily_frequencies.each do |current_daily_frequency| - current_daily_frequency.students.each do |student| - daily_frequency_students[student.student_id] ||= {} - daily_frequency_students[student.student_id][:present] = student.present || false - daily_frequency_students[student.student_id].reverse_merge!( - classroom_id: classroom_id, - frequency_date: frequency_date - ) - end - end + validate_parameters!(classroom_id, frequency_date, teacher_id) - create_or_update_unique_daily_frequency_students(daily_frequency_students, teacher_id) - else - remove_unique_daily_frequency_students(classroom_id, frequency_date) - end + frequency_students = set_daily_frequency_students(classroom_id, frequency_date) + + return remove_unique_daily_frequency_students(classroom_id, frequency_date) if frequency_students.blank? + + hash_frequency_students = build_hash_frequency_students(frequency_students, classroom_id, frequency_date) + + create_or_update_unique_daily_frequency_students(hash_frequency_students, teacher_id) end private + def set_daily_frequency_students(classroom_id, frequency_date) + DailyFrequencyStudent.joins(:daily_frequency) + .where( + daily_frequencies: { + classroom_id: classroom_id, frequency_date: frequency_date + }, + active: true + ) + .pluck(:student_id, :present) + end + + def build_hash_frequency_students(frequency_students, classroom_id, frequency_date) + frequency_students.to_h.transform_values do |present| + { + classroom_id: classroom_id, + frequency_date: frequency_date, + present: present || false + } + end + end + # Random time between 19h and 23h # But at least at 1 minute after the current time def perform_worker_time [ Date.current + rand(19...24).hours + rand(0...60).minutes + rand(0...60).seconds, - Time.current + 1.minute + 1.minute.from_now ].max end @@ -82,4 +91,10 @@ def remove_unique_daily_frequency_students(classroom_id, frequency_date) .frequency_date(frequency_date) .destroy_all end + + def validate_parameters!(classroom_id, frequency_date, teacher_id) + if classroom_id.blank? || frequency_date.blank? || teacher_id.blank? + raise ArgumentError, "Parâmetros inválidos: classroom_id, frequency_date ou teacher_id não estão presentes" + end + end end diff --git a/app/uploaders/doc_uploader.rb b/app/uploaders/doc_uploader.rb index 83f7dfeec..fa32d8b4c 100644 --- a/app/uploaders/doc_uploader.rb +++ b/app/uploaders/doc_uploader.rb @@ -3,7 +3,7 @@ def store_dir "#{Rails.env}/#{model.class.to_s.underscore.pluralize}/#{model.id}" end - def extension_white_list + def extension_whitelist %w[png jpeg jpg gif pdf odt doc docx ods xls xlsx odp ppt pptx odg xml csv] end diff --git a/app/uploaders/entity_logo_uploader.rb b/app/uploaders/entity_logo_uploader.rb index 52272ab33..a07198896 100644 --- a/app/uploaders/entity_logo_uploader.rb +++ b/app/uploaders/entity_logo_uploader.rb @@ -4,7 +4,7 @@ def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end - def extension_white_list + def extension_whitelist %w(jpg jpeg gif png) end end diff --git a/app/uploaders/user_profile_picture_uploader.rb b/app/uploaders/user_profile_picture_uploader.rb index 6e813edb3..02eb6ff56 100644 --- a/app/uploaders/user_profile_picture_uploader.rb +++ b/app/uploaders/user_profile_picture_uploader.rb @@ -4,7 +4,7 @@ def store_dir "uploads/#{model.class.to_s.underscore.pluralize}/#{mounted_as}/entity-#{Entity.current.id}/#{model.id}" end - def extension_white_list + def extension_whitelist %w(jpg jpeg gif png) end end diff --git a/app/validators/school_calendar_day_validator.rb b/app/validators/school_calendar_day_validator.rb index 79244b3ba..688f4ba02 100644 --- a/app/validators/school_calendar_day_validator.rb +++ b/app/validators/school_calendar_day_validator.rb @@ -9,7 +9,9 @@ def validate_each(record, attribute, value) message = '' grade_ids&.each do |grade_id| - school_day = false unless record.school_calendar.day_allows_entry?(value, grade_id, classroom_id, discipline_id) + school_day = false unless record.school_calendar.day_allows_entry?( + value, grade_id, classroom_id, discipline_id + ) step = record.school_calendar.steps.posting_date_after_and_before(value).first message = step ? I18n.t('errors.messages.not_school_calendar_day') : I18n.t('errors.messages.is_not_between_steps') diff --git a/app/views/avaliations/_form.html.erb b/app/views/avaliations/_form.html.erb index 51347a50d..365cc4a62 100644 --- a/app/views/avaliations/_form.html.erb +++ b/app/views/avaliations/_form.html.erb @@ -4,6 +4,15 @@ <%= simple_form_for @avaliation, html: { class: "smart-form" } do |f| %> <%= f.error_notification %> + <% if @avaliation.errors.any? %> +