/** * 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.ui.struts.action.administrativeOffice.gradeSubmission; import java.text.ParseException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.stream.Collectors; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.collections.comparators.ReverseComparator; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessages; import org.apache.struts.action.DynaActionForm; import org.apache.struts.util.LabelValueBean; import org.fenixedu.academic.domain.CurricularCourse; import org.fenixedu.academic.domain.Degree; import org.fenixedu.academic.domain.DegreeCurricularPlan; import org.fenixedu.academic.domain.EnrolmentEvaluation; import org.fenixedu.academic.domain.EvaluationSeason; import org.fenixedu.academic.domain.ExecutionSemester; import org.fenixedu.academic.domain.MarkSheet; import org.fenixedu.academic.domain.MarkSheetState; import org.fenixedu.academic.domain.accessControl.academicAdministration.AcademicAccessRule; import org.fenixedu.academic.domain.accessControl.academicAdministration.AcademicOperationType; import org.fenixedu.academic.domain.exceptions.DomainException; import org.fenixedu.academic.dto.degreeAdministrativeOffice.gradeSubmission.MarkSheetManagementSearchBean; import org.fenixedu.academic.dto.degreeAdministrativeOffice.gradeSubmission.MarkSheetSearchResultBean; import org.fenixedu.academic.predicate.AccessControl; import org.fenixedu.academic.service.services.administrativeOffice.gradeSubmission.SearchMarkSheets; import org.fenixedu.academic.service.services.exceptions.FenixServiceException; import org.fenixedu.academic.service.services.exceptions.InvalidArgumentsServiceException; import org.fenixedu.academic.service.services.manager.RemoveGradesFromConfirmedMarkSheet; import org.fenixedu.academic.ui.struts.action.academicAdministration.AcademicAdministrationApplication.AcademicAdminMarksheetApp; import org.fenixedu.academic.util.DateFormatUtil; import org.fenixedu.academic.util.report.ReportsUtils; import org.fenixedu.bennu.core.security.Authenticate; import org.fenixedu.bennu.struts.annotations.Forward; import org.fenixedu.bennu.struts.annotations.Mapping; import org.fenixedu.bennu.struts.portal.EntryPoint; import org.fenixedu.bennu.struts.portal.StrutsFunctionality; import org.joda.time.DateTime; import pt.ist.fenixWebFramework.renderers.utils.RenderUtils; import pt.ist.fenixframework.Atomic; import pt.ist.fenixframework.Atomic.TxMode; import pt.ist.fenixframework.FenixFramework; @StrutsFunctionality(app = AcademicAdminMarksheetApp.class, path = "search", titleKey = "link.markSheet.management") @Mapping(path = "/markSheetManagement", module = "academicAdministration", formBean = "markSheetManagementForm", input = "/gradeSubmission/markSheetManagement.jsp") @Forward(name = "searchMarkSheet", path = "/academicAdministration/gradeSubmission/markSheetManagement.jsp") @Forward(name = "viewMarkSheet", path = "/academicAdministration/gradeSubmission/viewMarkSheet.jsp") @Forward(name = "removeMarkSheet", path = "/academicAdministration/gradeSubmission/removeMarkSheet.jsp") @Forward(name = "searchMarkSheetFilled", path = "/academicAdministration/markSheetManagement.do?method=prepareSearchMarkSheetFilled") @Forward(name = "confirmMarkSheet", path = "/academicAdministration/gradeSubmission/confirmMarkSheet.jsp") @Forward(name = "listMarkSheet", path = "/manager/markSheet/viewMarkSheet.jsp") @Forward(name = "choosePrinterMarkSheetsWeb", path = "/academicAdministration/gradeSubmission/choosePrinterMarkSheetsWeb_bd.jsp") public class MarkSheetSearchDispatchAction extends MarkSheetDispatchAction { @EntryPoint public ActionForward prepareSearchMarkSheet(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { MarkSheetManagementSearchBean markSheetManagementSearchBean = new MarkSheetManagementSearchBean(); markSheetManagementSearchBean.setExecutionPeriod(ExecutionSemester.readActualExecutionSemester()); request.setAttribute("edit", markSheetManagementSearchBean); return mapping.findForward("searchMarkSheet"); } public ActionForward prepareSearchMarkSheetFilled(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws FenixServiceException { MarkSheetManagementSearchBean markSheetBean = new MarkSheetManagementSearchBean(); fillMarkSheetSearchBean(actionForm, request, markSheetBean); if (markSheetBean.getCurricularCourse() == null) { return prepareSearchMarkSheet(mapping, actionForm, request, response); } else { return searchMarkSheets(mapping, actionForm, request, response, markSheetBean); } } public ActionForward searchMarkSheets(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws FenixServiceException { MarkSheetManagementSearchBean searchBean = (MarkSheetManagementSearchBean) RenderUtils.getViewState().getMetaObject().getObject(); return searchMarkSheets(mapping, actionForm, request, response, searchBean); } private ActionForward searchMarkSheets(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response, MarkSheetManagementSearchBean searchBean) throws FenixServiceException { ActionMessages actionMessages = createActionMessages(); try { Map<EvaluationSeason, MarkSheetSearchResultBean> result = SearchMarkSheets.run(searchBean); request.setAttribute("edit", searchBean); request.setAttribute("searchResult", result); request.setAttribute("url", buildSearchUrl(searchBean)); } catch (InvalidArgumentsServiceException e) { addMessage(request, actionMessages, e.getMessage()); } return mapping.getInputForward(); } protected void fillMarkSheetSearchBean(ActionForm actionForm, HttpServletRequest request, MarkSheetManagementSearchBean markSheetBean) { DynaActionForm form = (DynaActionForm) actionForm; fillMarkSheetBean(actionForm, request, markSheetBean); if (form.getString("tn") != null && form.getString("tn").length() != 0) { markSheetBean.setTeacherId(form.getString("tn")); } try { markSheetBean.setEvaluationDate(DateFormatUtil.parse("dd/MM/yyyy", form.getString("ed"))); } catch (ParseException e) { markSheetBean.setEvaluationDate(null); } if (form.getString("mss") != null && form.getString("mss").length() != 0) { markSheetBean.setMarkSheetState(MarkSheetState.valueOf(form.getString("mss"))); } if (form.getString("mst") != null && form.getString("mst").length() != 0) { markSheetBean.setEvaluationSeason(FenixFramework.<EvaluationSeason> getDomainObject(form.getString("mst"))); } } private String buildSearchUrl(MarkSheetManagementSearchBean searchBean) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("&epID=").append(searchBean.getExecutionPeriod().getExternalId()); stringBuilder.append("&dID=").append(searchBean.getDegree().getExternalId()); stringBuilder.append("&dcpID=").append(searchBean.getDegreeCurricularPlan().getExternalId()); stringBuilder.append("&ccID=").append(searchBean.getCurricularCourse().getExternalId()); if (searchBean.getTeacherId() != null) { stringBuilder.append("&tn=").append(searchBean.getTeacherId()); } if (searchBean.getEvaluationDate() != null) { stringBuilder.append("&ed=").append(DateFormatUtil.format("dd/MM/yyyy", searchBean.getEvaluationDate())); } if (searchBean.getMarkSheetState() != null) { stringBuilder.append("&mss=").append(searchBean.getMarkSheetState().getName()); } if (searchBean.getEvaluationSeason() != null) { stringBuilder.append("&mst=").append(searchBean.getEvaluationSeason().getExternalId()); } return stringBuilder.toString(); } public ActionForward prepareViewRectificationMarkSheet(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { DynaActionForm form = (DynaActionForm) actionForm; EnrolmentEvaluation enrolmentEvaluation = getDomainObject(form, "evaluationID"); MarkSheet markSheet = enrolmentEvaluation.getRectificationMarkSheet(); request.setAttribute("markSheet", markSheet); request.setAttribute("url", buildUrl(form)); return mapping.findForward("viewMarkSheet"); } public ActionForward searchConfirmedMarkSheets(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { MarkSheetManagementSearchBean searchBean = getRenderedObject(); Collection<MarkSheet> result = new ArrayList<MarkSheet>(); for (MarkSheet markSheet : searchBean.getCurricularCourse().getMarkSheetsSet()) { if (markSheet.getExecutionPeriod() == searchBean.getExecutionPeriod() && markSheet.isConfirmed()) { result.add(markSheet); } } request.setAttribute("edit", searchBean); request.setAttribute("searchResult", result); request.setAttribute("url", buildSearchUrl(searchBean)); return mapping.findForward("searchMarkSheet"); } public ActionForward listMarkSheet(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { DynaActionForm form = (DynaActionForm) actionForm; MarkSheet markSheet = getDomainObject(form, "msID"); request.setAttribute("markSheet", markSheet); request.setAttribute("url", buildUrl(form)); return mapping.findForward("listMarkSheet"); } public ActionForward searchConfirmedMarkSheetsFilled(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { MarkSheetManagementSearchBean searchBean = new MarkSheetManagementSearchBean(); fillMarkSheetBean(actionForm, request, searchBean); Collection<MarkSheet> result = new ArrayList<MarkSheet>(); for (MarkSheet markSheet : searchBean.getCurricularCourse().getMarkSheetsSet()) { if (markSheet.getExecutionPeriod() == searchBean.getExecutionPeriod() && markSheet.isConfirmed()) { result.add(markSheet); } } request.setAttribute("edit", searchBean); request.setAttribute("searchResult", result); request.setAttribute("url", buildSearchUrl(searchBean)); return mapping.findForward("searchMarkSheet"); } public ActionForward removeGrades(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws FenixServiceException { DynaActionForm form = (DynaActionForm) actionForm; MarkSheet markSheet = getDomainObject(form, "msID"); List<EnrolmentEvaluation> evaluations = getEvaluationsToRemove(form); try { RemoveGradesFromConfirmedMarkSheet.run(markSheet, evaluations); } catch (DomainException e) { addActionMessage(request, e.getMessage()); return listMarkSheet(mapping, actionForm, request, response); } return prepareSearchMarkSheetFilled(mapping, actionForm, request, response); } private List<EnrolmentEvaluation> getEvaluationsToRemove(DynaActionForm actionForm) { List<EnrolmentEvaluation> res = new ArrayList<EnrolmentEvaluation>(); String[] evaluationsToRemove = (String[]) actionForm.get("evaluationsToRemove"); for (String eeID : evaluationsToRemove) { EnrolmentEvaluation enrolmentEvaluation = FenixFramework.getDomainObject(eeID); if (enrolmentEvaluation != null) { res.add(enrolmentEvaluation); } } return res; } public ActionForward choosePrinterMarkSheetsWeb(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { return choosePrinterMarkSheetsWeb(mapping, actionForm, request, response, ExecutionSemester.readActualExecutionSemester(), null); } public ActionForward choosePrinterMarkSheetsWebPostBack(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { final DynaActionForm form = (DynaActionForm) actionForm; final ExecutionSemester executionSemester = getExecutionSemester(form); final DegreeCurricularPlan degreeCurricularPlan = getDegreeCurricularPlan(form); return choosePrinterMarkSheetsWeb(mapping, actionForm, request, response, executionSemester, degreeCurricularPlan); } private ExecutionSemester getExecutionSemester(DynaActionForm form) { return getDomainObject(form, "ecID"); } private DegreeCurricularPlan getDegreeCurricularPlan(DynaActionForm form) { return getDomainObject(form, "dcpID"); } private ActionForward choosePrinterMarkSheetsWeb(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response, ExecutionSemester executionSemester, DegreeCurricularPlan degreeCurricularPlan) { DynaActionForm form = (DynaActionForm) actionForm; final Collection<MarkSheet> webMarkSheetsNotPrinted = executionSemester.getWebMarkSheetsNotPrinted(AccessControl.getPerson(), degreeCurricularPlan); request.setAttribute("executionPeriod", executionSemester); request.setAttribute("curricularCourseMap", buildMapWithCurricularCoursesAndNumberOfMarkSheets(webMarkSheetsNotPrinted)); request.setAttribute("totalMarkSheetsCount", webMarkSheetsNotPrinted.size()); buildPeriods(request); buildDegreeCurricularPlans(request, executionSemester); form.set("ecID", executionSemester.getExternalId().toString()); if (degreeCurricularPlan != null) { form.set("dcpID", degreeCurricularPlan.getExternalId().toString()); } return mapping.findForward("choosePrinterMarkSheetsWeb"); } private void buildDegreeCurricularPlans(HttpServletRequest request, ExecutionSemester semester) { final List<DegreeCurricularPlan> dcps = new ArrayList<DegreeCurricularPlan>(semester.getExecutionYear().getDegreeCurricularPlans()); Collections.sort(dcps, DegreeCurricularPlan.COMPARATOR_BY_PRESENTATION_NAME); final List<LabelValueBean> result = new ArrayList<LabelValueBean>(); Set<Degree> degreesForMarksheets = AcademicAccessRule .getDegreesAccessibleToFunction(AcademicOperationType.MANAGE_MARKSHEETS, Authenticate.getUser()).collect( Collectors.toSet()); for (final DegreeCurricularPlan dcp : dcps) { if (degreesForMarksheets.contains(dcp.getDegree())) { result.add(new LabelValueBean(dcp.getPresentationName(semester.getExecutionYear()), dcp.getExternalId() .toString())); } } request.setAttribute("degreeCurricularPlans", result); } private void buildPeriods(HttpServletRequest request) { final List<ExecutionSemester> notClosedExecutionPeriods = ExecutionSemester.readNotClosedExecutionPeriods(); Collections.sort(notClosedExecutionPeriods, new ReverseComparator(ExecutionSemester.COMPARATOR_BY_SEMESTER_AND_YEAR)); final List<LabelValueBean> periods = new ArrayList<LabelValueBean>(); for (final ExecutionSemester period : notClosedExecutionPeriods) { periods.add(new LabelValueBean(period.getExecutionYear().getYear() + " - " + period.getName(), period.getExternalId() .toString())); } request.setAttribute("periods", periods); } private Map<CurricularCourse, Integer> buildMapWithCurricularCoursesAndNumberOfMarkSheets( Collection<MarkSheet> webMarkSheetsNotPrinted) { final Map<CurricularCourse, Integer> result = new TreeMap<CurricularCourse, Integer>(new Comparator<CurricularCourse>() { @Override public int compare(CurricularCourse o1, CurricularCourse o2) { return o1.getName().compareTo(o2.getName()); } }); for (final MarkSheet markSheet : webMarkSheetsNotPrinted) { Integer markSheetNumber = result.get(markSheet.getCurricularCourse()); result.put(markSheet.getCurricularCourse(), (markSheetNumber == null) ? Integer.valueOf(1) : Integer.valueOf(markSheetNumber.intValue() + 1)); } return result; } public ActionForward printMarkSheets(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws FenixServiceException { DynaActionForm form = (DynaActionForm) actionForm; if (form.get("msID") != null) { form.set("markSheet", form.get("msID")); } if (form.get("markSheet") == null || form.getString("markSheet").length() == 0) { form.set("markSheet", request.getParameter("markSheet")); } String markSheet = form.getString("markSheet"); if (markSheet.equals("all")) { return printWebMarkSheets(mapping, actionForm, request, response); } else { return printMarkSheet(mapping, actionForm, request, response); } } private ActionForward printMarkSheet(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws FenixServiceException { DynaActionForm form = (DynaActionForm) actionForm; String markSheetString = form.getString("markSheet"); MarkSheet markSheet = getDomainObject(form, "markSheet"); ActionMessages actionMessages = new ActionMessages(); try (ServletOutputStream writer = response.getOutputStream()) { MarkSheetDocument document = new MarkSheetDocument(markSheet); byte[] data = ReportsUtils.generateReport(document).getData(); response.setContentLength(data.length); response.setContentType("application/pdf"); response.addHeader("Content-Disposition", String.format("attachment; filename=%s.pdf", document.getReportFileName())); writer.write(data); markAsPrinted(markSheet); return null; } catch (Exception e) { request.setAttribute("markSheet", markSheetString); addMessage(request, actionMessages, e.getMessage()); return choosePrinterMarkSheetsWeb(mapping, actionForm, request, response); } } private ActionForward printWebMarkSheets(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws FenixServiceException { final DynaActionForm form = (DynaActionForm) actionForm; final ActionMessages actionMessages = new ActionMessages(); try (ServletOutputStream writer = response.getOutputStream()) { Collection<MarkSheet> markSheets = getExecutionSemester(form).getWebMarkSheetsNotPrinted(AccessControl.getPerson(), getDegreeCurricularPlan(form)); List<MarkSheetDocument> reports = markSheets.stream().map(MarkSheetDocument::new).collect(Collectors.toList()); byte[] data = ReportsUtils.generateReport(reports.toArray(new MarkSheetDocument[0])).getData(); response.setContentLength(data.length); response.setContentType("application/pdf"); response.addHeader("Content-Disposition", String.format("attachment; filename=%s.pdf", "marksheets-" + new DateTime().toString())); writer.write(data); markAsPrinted(markSheets); return null; } catch (Exception e) { addMessage(request, actionMessages, e.getMessage()); return choosePrinterMarkSheetsWeb(mapping, actionForm, request, response); } } @Atomic(mode = TxMode.WRITE) private void markAsPrinted(Collection<MarkSheet> markSheets) { markSheets.forEach(markSheet -> { if (!markSheet.getPrinted()) { markSheet.setPrinted(Boolean.TRUE); } }); } @Atomic(mode = TxMode.WRITE) private void markAsPrinted(MarkSheet markSheet) { if (!markSheet.getPrinted()) { markSheet.setPrinted(Boolean.TRUE); } } }