/** * Copyright © 2002 Instituto Superior Técnico * * This file is part of FenixEdu Academic. * * FenixEdu Academic is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * FenixEdu Academic is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with FenixEdu Academic. If not, see <http://www.gnu.org/licenses/>. */ package org.fenixedu.academic.service.services.teacher; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.fenixedu.academic.domain.Attends; import org.fenixedu.academic.domain.Evaluation; import org.fenixedu.academic.domain.EvaluationManagementLog; import org.fenixedu.academic.domain.ExecutionCourse; import org.fenixedu.academic.domain.Mark; import org.fenixedu.academic.domain.exceptions.DomainException; import org.fenixedu.academic.domain.exceptions.InvalidMarkDomainException; import org.fenixedu.academic.domain.student.Student; import org.fenixedu.academic.domain.student.registrationStates.RegistrationState; import org.fenixedu.academic.domain.studentCurriculum.CycleCurriculumGroup; import org.fenixedu.academic.service.services.exceptions.FenixServiceException; import org.fenixedu.academic.service.services.exceptions.FenixServiceMultipleException; import org.fenixedu.academic.util.Bundle; import pt.ist.fenixframework.Atomic; import pt.ist.fenixframework.FenixFramework; public class WriteMarks { @Atomic public static void writeByStudent(final String executioCourseOID, final String evaluationOID, final List<StudentMark> marks) throws FenixServiceException { final Evaluation evaluation = FenixFramework.getDomainObject(evaluationOID); final ExecutionCourse executionCourse = FenixFramework.getDomainObject(executioCourseOID); writeMarks(convertMarks(executionCourse, marks), executionCourse, evaluation); } @Atomic public static void writeByAttend(final String executioCourseOID, final String evaluationOID, final List<AttendsMark> marks) throws FenixServiceException { final Evaluation evaluation = FenixFramework.getDomainObject(evaluationOID); final ExecutionCourse executionCourse = FenixFramework.getDomainObject(executioCourseOID); writeMarks(marks, executionCourse, evaluation); } private static List<AttendsMark> convertMarks(final ExecutionCourse executionCourse, final List<StudentMark> marks) throws FenixServiceMultipleException { final List<DomainException> exceptionList = new ArrayList<DomainException>(); final List<AttendsMark> result = new ArrayList<AttendsMark>(); for (final StudentMark studentMark : marks) { final Attends attend = findAttend(executionCourse, studentMark.studentNumber, exceptionList); if (attend != null) { addMark(result, studentMark, attend, exceptionList); } } if (!exceptionList.isEmpty()) { throw new FenixServiceMultipleException(exceptionList); } return result; } private static void addMark(List<AttendsMark> result, StudentMark studentMark, Attends attend, List<DomainException> exceptionList) { if (studentMark.mark.length() - studentMark.mark.indexOf('.') - 1 > 2) { exceptionList.add(new DomainException("error.mark.more.than.two.decimals", studentMark.studentNumber)); } else { result.add(new AttendsMark(attend.getExternalId(), studentMark.mark)); } } private static Attends findAttend(final ExecutionCourse executionCourse, final String studentNumber, final List<DomainException> exceptionList) { final List<Attends> activeAttends = new ArrayList<Attends>(2); for (final Attends attend : executionCourse.getAttendsSet()) { final Student student = attend.getRegistration().getStudent(); if ((student.getPerson().getUsername().equals(studentNumber) || student.getNumber().toString().equals(studentNumber)) && (isActive(attend) || belongsToActiveExternalCycle(attend))) { activeAttends.add(attend); } } if (activeAttends.size() == 1) { return activeAttends.iterator().next(); } if (activeAttends.isEmpty()) { exceptionList.add(new DomainException("errors.student.without.active.attends", studentNumber)); } else { exceptionList.add(new DomainException("errors.student.with.several.active.attends", studentNumber)); } return null; } private static boolean belongsToActiveExternalCycle(final Attends attend) { if (attend.getEnrolment() != null) { final CycleCurriculumGroup cycle = attend.getEnrolment().getParentCycleCurriculumGroup(); if (cycle != null && cycle.isExternal()) { final Student student = attend.getRegistration().getStudent(); return student.getActiveRegistrationFor(cycle.getDegreeCurricularPlanOfDegreeModule()) != null; } } return false; } private static boolean isActive(final Attends attends) { final RegistrationState state; if (attends.getEnrolment() != null) { state = attends.getEnrolment().getRegistration().getLastRegistrationState(attends.getExecutionYear()); } else { state = attends.getRegistration().getLastRegistrationState(attends.getExecutionYear()); } return state != null && state.isActive(); } private static void writeMarks(final List<AttendsMark> marks, final ExecutionCourse executionCourse, final Evaluation evaluation) throws FenixServiceMultipleException { final List<DomainException> exceptionList = new ArrayList<DomainException>(); for (final AttendsMark entry : marks) { final Attends attend = findAttend(executionCourse, entry.attendId); final String markValue = entry.mark; if (attend.getEnrolment() != null && attend.getEnrolment().isImpossible()) { exceptionList.add(new DomainException("errors.student.with.impossible.enrolment", attend.getRegistration() .getStudent().getNumber().toString())); } else { final Mark mark = attend.getMarkByEvaluation(evaluation); if (isToDeleteMark(markValue)) { if (mark != null) { mark.delete(); } } else { try { if (mark == null) { evaluation.addNewMark(attend, markValue); } else { mark.setMark(markValue); } } catch (InvalidMarkDomainException e) { exceptionList.add(e); } } } } if (!exceptionList.isEmpty()) { throw new FenixServiceMultipleException(exceptionList); } EvaluationManagementLog.createLog(executionCourse, Bundle.MESSAGING, "log.executionCourse.evaluation.generic.edited.marks", evaluation.getPresentationName(), executionCourse.getName(), executionCourse.getDegreePresentationString()); } private static Attends findAttend(final ExecutionCourse executionCourse, final String attendId) { for (final Attends attend : executionCourse.getAttendsSet()) { if (attend.getExternalId().equals(attendId)) { return attend; } } return null; } private static boolean isToDeleteMark(final String markValue) { return markValue == null || markValue.isEmpty(); } public static class StudentMark implements Serializable { private final String studentNumber; private final String mark; public StudentMark(final String studentNumber, final String mark) { this.studentNumber = studentNumber; this.mark = mark; } } public static class AttendsMark implements Serializable { private final String attendId; private final String mark; public AttendsMark(final String attendId, final String mark) { this.attendId = attendId; this.mark = mark; } } }