org.fenixedu.ulisboa.specifications.ui.evaluation.managemarksheet.administrative.CompetenceCourseMarkSheetController.java Source code

Java tutorial

Introduction

Here is the source code for org.fenixedu.ulisboa.specifications.ui.evaluation.managemarksheet.administrative.CompetenceCourseMarkSheetController.java

Source

/**
 * This file was created by Quorum Born IT <http://www.qub-it.com/> and its 
 * copyright terms are bind to the legal agreement regulating the FenixEdu@ULisboa 
 * software development project between Quorum Born IT and Servios Partilhados da
 * Universidade de Lisboa:
 *  - Copyright  2015 Quorum Born IT (until any Go-Live phase)
 *  - Copyright  2015 Universidade de Lisboa (after any Go-Live phase)
 *
 * Contributors: luis.egidio@qub-it.com
 *
 * 
 * This file is part of FenixEdu Specifications.
 *
 * FenixEdu Specifications 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 Specifications 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 Specifications.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.fenixedu.ulisboa.specifications.ui.evaluation.managemarksheet.administrative;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.fenixedu.academic.domain.CompetenceCourse;
import org.fenixedu.academic.domain.EvaluationSeason;
import org.fenixedu.academic.domain.ExecutionSemester;
import org.fenixedu.bennu.core.domain.Bennu;
import org.fenixedu.bennu.core.i18n.BundleUtil;
import org.fenixedu.bennu.core.security.Authenticate;
import org.fenixedu.bennu.spring.portal.SpringFunctionality;
import org.fenixedu.commons.spreadsheet.SheetData;
import org.fenixedu.commons.spreadsheet.SpreadsheetBuilder;
import org.fenixedu.commons.spreadsheet.WorkbookExportFormat;
import org.fenixedu.ulisboa.specifications.domain.evaluation.markSheet.CompetenceCourseMarkSheet;
import org.fenixedu.ulisboa.specifications.domain.evaluation.markSheet.CompetenceCourseMarkSheetChangeRequest;
import org.fenixedu.ulisboa.specifications.domain.evaluation.markSheet.CompetenceCourseMarkSheetChangeRequestStateEnum;
import org.fenixedu.ulisboa.specifications.domain.evaluation.markSheet.CompetenceCourseMarkSheetSnapshot;
import org.fenixedu.ulisboa.specifications.domain.evaluation.markSheet.CompetenceCourseMarkSheetStateEnum;
import org.fenixedu.ulisboa.specifications.domain.evaluation.season.EvaluationSeasonServices;
import org.fenixedu.ulisboa.specifications.domain.exceptions.ULisboaSpecificationsDomainException;
import org.fenixedu.ulisboa.specifications.domain.file.ULisboaSpecificationsTemporaryFile;
import org.fenixedu.ulisboa.specifications.dto.evaluation.markSheet.CompetenceCourseMarkSheetBean;
import org.fenixedu.ulisboa.specifications.dto.evaluation.markSheet.report.CompetenceCourseSeasonReport;
import org.fenixedu.ulisboa.specifications.service.evaluation.MarkSheetDocumentPrintService;
import org.fenixedu.ulisboa.specifications.service.evaluation.MarkSheetImportExportService;
import org.fenixedu.ulisboa.specifications.service.evaluation.MarkSheetStatusReportService;
import org.fenixedu.ulisboa.specifications.ui.FenixeduUlisboaSpecificationsBaseController;
import org.fenixedu.ulisboa.specifications.ui.FenixeduUlisboaSpecificationsController;
import org.fenixedu.ulisboa.specifications.util.ULisboaConstants;
import org.fenixedu.ulisboa.specifications.util.ULisboaSpecificationsUtil;
import org.joda.time.DateTime;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.google.common.base.Joiner;

import pt.ist.fenixframework.Atomic;
import pt.ist.fenixframework.Atomic.TxMode;

@Component("org.fenixedu.ulisboa.specifications.evaluation.manageMarkSheet.administrative")
@SpringFunctionality(app = FenixeduUlisboaSpecificationsController.class, title = "label.title.evaluation.manageMarkSheet.administrative", accessGroup = "academic(MANAGE_MARKSHEETS)")
@RequestMapping(CompetenceCourseMarkSheetController.CONTROLLER_URL)
public class CompetenceCourseMarkSheetController extends FenixeduUlisboaSpecificationsBaseController {

    public static final String CONTROLLER_URL = "/fenixedu-ulisboa-specifications/evaluation/managemarksheet/administrative/competencecoursemarksheet";

    private static final String JSP_PATH = CONTROLLER_URL.substring(1);

    private String jspPage(final String page) {
        return JSP_PATH + "/" + page;
    }

    @RequestMapping
    public String home(final Model model) {
        return "forward:" + CONTROLLER_URL + "/";
    }

    private CompetenceCourseMarkSheetBean getCompetenceCourseMarkSheetBean(final Model model) {
        return (CompetenceCourseMarkSheetBean) model.asMap().get("competenceCourseMarkSheetBean");
    }

    private void setCompetenceCourseMarkSheetBean(final CompetenceCourseMarkSheetBean bean, final Model model) {
        model.addAttribute("competenceCourseMarkSheetBeanJson", getBeanJson(bean));
        model.addAttribute("competenceCourseMarkSheetBean", bean);
    }

    private CompetenceCourseMarkSheet getCompetenceCourseMarkSheet(final Model model) {
        return (CompetenceCourseMarkSheet) model.asMap().get("competenceCourseMarkSheet");
    }

    private void setCompetenceCourseMarkSheet(final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            final Model model) {
        model.addAttribute("competenceCourseMarkSheet", competenceCourseMarkSheet);
    }

    private static final String _SEARCH_URI = "/";
    public static final String SEARCH_URL = CONTROLLER_URL + _SEARCH_URI;

    @RequestMapping(value = _SEARCH_URI)
    public String search(
            @RequestParam(value = "executionsemester", required = false) ExecutionSemester executionSemester,
            @RequestParam(value = "competencecourse", required = false) CompetenceCourse competenceCourse,
            final Model model) {
        final List<CompetenceCourseMarkSheet> searchResultsDataSet = filterSearch(executionSemester,
                competenceCourse, (CompetenceCourseMarkSheetStateEnum) null, (EvaluationSeason) null,
                (CompetenceCourseMarkSheetChangeRequestStateEnum) null);

        final CompetenceCourseMarkSheetBean bean = new CompetenceCourseMarkSheetBean();
        bean.update();
        setCompetenceCourseMarkSheetBean(bean, model);

        model.addAttribute("searchcompetencecoursemarksheetResultsDataSet", searchResultsDataSet);
        return jspPage("search");
    }

    @RequestMapping(value = _SEARCH_URI, method = RequestMethod.POST)
    public String search(@RequestParam(value = "bean", required = false) final CompetenceCourseMarkSheetBean bean,
            final Model model) {

        setCompetenceCourseMarkSheetBean(bean, model);

        model.addAttribute("searchcompetencecoursemarksheetResultsDataSet",
                filterSearch(bean.getExecutionSemester(), bean.getCompetenceCourse(), bean.getMarkSheetState(),
                        bean.getEvaluationSeason(), bean.getChangeRequestState()));

        return jspPage("search");
    }

    private static final String _SEARCHPOSTBACK_URI = "/searchpostback/";
    public static final String SEARCHPOSTBACK_URL = CONTROLLER_URL + _SEARCHPOSTBACK_URI;

    @RequestMapping(value = _SEARCHPOSTBACK_URI, method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    public @ResponseBody ResponseEntity<String> searchpostback(
            @RequestParam(value = "bean", required = false) final CompetenceCourseMarkSheetBean bean,
            final Model model) {

        bean.update();
        this.setCompetenceCourseMarkSheetBean(bean, model);
        return new ResponseEntity<String>(getBeanJson(bean), HttpStatus.OK);
    }

    private Stream<CompetenceCourseMarkSheet> getSearchUniverseSearchDataSet(
            final ExecutionSemester executionSemester, final CompetenceCourse competenceCourse,
            final CompetenceCourseMarkSheetStateEnum markSheetState, final EvaluationSeason evaluationSeason,
            CompetenceCourseMarkSheetChangeRequestStateEnum changeRequestState) {
        return CompetenceCourseMarkSheet.findBy(executionSemester, competenceCourse, markSheetState,
                evaluationSeason, changeRequestState);
    }

    private List<CompetenceCourseMarkSheet> filterSearch(final ExecutionSemester executionSemester,
            final CompetenceCourse competenceCourse, final CompetenceCourseMarkSheetStateEnum markSheetState,
            final EvaluationSeason evaluationSeason,
            final CompetenceCourseMarkSheetChangeRequestStateEnum changeRequestState) {

        return getSearchUniverseSearchDataSet(executionSemester, competenceCourse, markSheetState, evaluationSeason,
                changeRequestState).collect(Collectors.toList());
    }

    private static final String _SEARCH_TO_VIEW_ACTION_URI = "/search/view/";
    public static final String SEARCH_TO_VIEW_ACTION_URL = CONTROLLER_URL + _SEARCH_TO_VIEW_ACTION_URI;

    @RequestMapping(value = _SEARCH_TO_VIEW_ACTION_URI + "{oid}")
    public String processSearchToViewAction(
            @PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet, final Model model,
            final RedirectAttributes redirectAttributes) {

        return redirect(READ_URL + competenceCourseMarkSheet.getExternalId(), model, redirectAttributes);
    }

    private static final String _READ_URI = "/read/";
    public static final String READ_URL = CONTROLLER_URL + _READ_URI;

    @RequestMapping(value = _READ_URI + "{oid}")
    public String read(@PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            final Model model) {
        setCompetenceCourseMarkSheet(competenceCourseMarkSheet, model);
        return jspPage("read");
    }

    private static final String _DELETE_URI = "/delete/";
    public static final String DELETE_URL = CONTROLLER_URL + _DELETE_URI;

    @RequestMapping(value = _DELETE_URI + "{oid}", method = RequestMethod.POST)
    public String delete(@PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            final Model model, final RedirectAttributes redirectAttributes) {

        setCompetenceCourseMarkSheet(competenceCourseMarkSheet, model);
        try {
            competenceCourseMarkSheet.delete();

            addInfoMessage(ULisboaSpecificationsUtil.bundle("label.success.delete"), model);
            return redirect(CONTROLLER_URL, model, redirectAttributes);

        } catch (Exception ex) {
            addErrorMessage(ex.getLocalizedMessage(), model);
        }

        return jspPage("read/" + getCompetenceCourseMarkSheet(model).getExternalId());
    }

    @RequestMapping(value = "/read/{oid}/updateevaluations")
    public String processReadToUpdateEvaluations(
            @PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet, final Model model,
            final RedirectAttributes redirectAttributes) {

        setCompetenceCourseMarkSheet(competenceCourseMarkSheet, model);

        return redirect(UPDATEEVALUATIONS_URL + getCompetenceCourseMarkSheet(model).getExternalId(), model,
                redirectAttributes);
    }

    private static final String _UPDATE_URI = "/update/";
    public static final String UPDATE_URL = CONTROLLER_URL + _UPDATE_URI;

    @RequestMapping(value = _UPDATE_URI + "{oid}", method = RequestMethod.GET)
    public String update(@PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            final Model model) {
        setCompetenceCourseMarkSheet(competenceCourseMarkSheet, model);

        final CompetenceCourseMarkSheetBean bean = new CompetenceCourseMarkSheetBean(competenceCourseMarkSheet);
        this.setCompetenceCourseMarkSheetBean(bean, model);

        return jspPage("update");
    }

    private static final String _UPDATEPOSTBACK_URI = "/updatepostback/";
    public static final String UPDATEPOSTBACK_URL = CONTROLLER_URL + _UPDATEPOSTBACK_URI;

    @RequestMapping(value = _UPDATEPOSTBACK_URI
            + "{oid}", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    public @ResponseBody ResponseEntity<String> updatepostback(
            @PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            @RequestParam(value = "bean", required = false) final CompetenceCourseMarkSheetBean bean,
            final Model model) {

        bean.update();
        this.setCompetenceCourseMarkSheetBean(bean, model);
        return new ResponseEntity<String>(getBeanJson(bean), HttpStatus.OK);
    }

    @RequestMapping(value = _UPDATE_URI + "{oid}", method = RequestMethod.POST)
    public String update(@PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            @RequestParam(value = "bean", required = false) final CompetenceCourseMarkSheetBean bean,
            final Model model, final RedirectAttributes redirectAttributes) {

        setCompetenceCourseMarkSheet(competenceCourseMarkSheet, model);

        try {

            competenceCourseMarkSheet.edit(bean.getEvaluationDate(), bean.getGradeScale(), bean.getCertifier(),
                    bean.getExpireDate());

            return redirect(READ_URL + getCompetenceCourseMarkSheet(model).getExternalId(), model,
                    redirectAttributes);
        } catch (Exception de) {

            addErrorMessage(de.getLocalizedMessage(), model);
            setCompetenceCourseMarkSheet(competenceCourseMarkSheet, model);
            this.setCompetenceCourseMarkSheetBean(bean, model);

            return jspPage("update");
        }
    }

    private static final String _CREATE_URI = "/create/";
    public static final String CREATE_URL = CONTROLLER_URL + _CREATE_URI;

    @RequestMapping(value = _CREATE_URI, method = RequestMethod.GET)
    public String create(final Model model) {
        final CompetenceCourseMarkSheetBean bean = new CompetenceCourseMarkSheetBean();
        this.setCompetenceCourseMarkSheetBean(bean, model);

        return jspPage("create");
    }

    private static final String _CREATEPOSTBACK_URI = "/createpostback/";
    public static final String CREATEPOSTBACK_URL = CONTROLLER_URL + _CREATEPOSTBACK_URI;

    @RequestMapping(value = _CREATEPOSTBACK_URI, method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    public @ResponseBody ResponseEntity<String> createpostback(
            @RequestParam(value = "bean", required = false) final CompetenceCourseMarkSheetBean bean,
            final Model model) {

        bean.update();
        this.setCompetenceCourseMarkSheetBean(bean, model);
        return new ResponseEntity<String>(getBeanJson(bean), HttpStatus.OK);
    }

    @RequestMapping(value = _CREATE_URI, method = RequestMethod.POST)
    public String create(@RequestParam(value = "bean", required = false) final CompetenceCourseMarkSheetBean bean,
            final Model model, final RedirectAttributes redirectAttributes) {

        try {
            final CompetenceCourseMarkSheet markSheet = CompetenceCourseMarkSheet.create(
                    bean.getExecutionSemester(), bean.getCompetenceCourse(), bean.getExecutionCourse(),
                    bean.getEvaluationSeason(), bean.getEvaluationDate(), bean.getCertifier(), bean.getShifts(),
                    false);

            model.addAttribute("competenceCourseMarkSheet", markSheet);
            return redirect(UPDATEEVALUATIONS_URL + getCompetenceCourseMarkSheet(model).getExternalId(), model,
                    redirectAttributes);

        } catch (Exception de) {

            addErrorMessage(de.getLocalizedMessage(), model);
            this.setCompetenceCourseMarkSheetBean(bean, model);
            return jspPage("create");
        }
    }

    private static final String _UPDATEEVALUATIONS_URI = "/updateevaluations/";
    public static final String UPDATEEVALUATIONS_URL = CONTROLLER_URL + _UPDATEEVALUATIONS_URI;

    @RequestMapping(value = _UPDATEEVALUATIONS_URI + "{oid}", method = RequestMethod.GET)
    public String updateevaluations(@PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            final Model model) {
        setCompetenceCourseMarkSheet(competenceCourseMarkSheet, model);

        final CompetenceCourseMarkSheetBean bean = new CompetenceCourseMarkSheetBean(competenceCourseMarkSheet);
        this.setCompetenceCourseMarkSheetBean(bean, model);

        return jspPage("updateevaluations");
    }

    private static final String _UPDATEEVALUATIONSPOSTBACK_URI = "/updateevaluationspostback/";
    public static final String UPDATEEVALUATIONSPOSTBACK_URL = CONTROLLER_URL + _UPDATEEVALUATIONSPOSTBACK_URI;

    @RequestMapping(value = _UPDATEEVALUATIONSPOSTBACK_URI
            + "{oid}", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    public @ResponseBody ResponseEntity<String> updateevaluationspostback(
            @PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            @RequestParam(value = "bean", required = false) final CompetenceCourseMarkSheetBean bean,
            final Model model) {

        this.setCompetenceCourseMarkSheetBean(bean, model);
        return new ResponseEntity<String>(getBeanJson(bean), HttpStatus.OK);
    }

    @RequestMapping(value = _UPDATEEVALUATIONS_URI + "{oid}", method = RequestMethod.POST)
    public String updateevaluations(@PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            @RequestParam(value = "bean", required = false) final CompetenceCourseMarkSheetBean bean,
            final Model model, final RedirectAttributes redirectAttributes) {
        setCompetenceCourseMarkSheet(competenceCourseMarkSheet, model);

        try {
            bean.updateEnrolmentEvaluations();

            return redirect(READ_URL + getCompetenceCourseMarkSheet(model).getExternalId(), model,
                    redirectAttributes);
        } catch (Exception de) {
            addErrorMessage(de.getLocalizedMessage(), model);
            this.setCompetenceCourseMarkSheetBean(bean, model);

            return jspPage("updateevaluations");
        }
    }

    private static final String _PRINT_URI = "/print/";
    public static final String PRINT_URL = CONTROLLER_URL + _PRINT_URI;

    @RequestMapping(value = _PRINT_URI + "{oid}")
    public void print(@PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            final Model model, final HttpServletResponse response) throws IOException {

        final CompetenceCourse competenceCourse = competenceCourseMarkSheet.getCompetenceCourse();
        final String filename = competenceCourse.getCode() + "_"
                + competenceCourse.getName().replace(' ', '_').replace('/', '-').replace('\\', '-')
                + competenceCourseMarkSheet.getEvaluationDate().toString("yyyy-MM-dd") + ".pdf";

        writeFile(response, filename, MarkSheetDocumentPrintService.PDF,
                MarkSheetDocumentPrintService.print(competenceCourseMarkSheet));
    }

    private static final String _PRINT_SNAPSHOT_URI = "/printsnapshot/";
    public static final String PRINT_SNAPSHOT_URL = CONTROLLER_URL + _PRINT_SNAPSHOT_URI;

    @RequestMapping(value = _PRINT_SNAPSHOT_URI + "{oid}")
    public void printSnapshot(@PathVariable("oid") final CompetenceCourseMarkSheetSnapshot snapshot,
            final Model model, final HttpServletResponse response) throws IOException {

        final String filename = snapshot.getCompetenceCourseCode() + "_" + snapshot.getCompetenceCourseName()
                .getContent().replace(' ', '_').replace('/', '-').replace('\\', '-')
                + snapshot.getEvaluationDate().toString("yyyy-MM-dd") + ".pdf";

        writeFile(response, filename, MarkSheetDocumentPrintService.PDF,
                MarkSheetDocumentPrintService.print(snapshot));
    }

    private static final String _CONFIRM_URI = "/confirm/";
    public static final String CONFIRM_URL = CONTROLLER_URL + _CONFIRM_URI;

    @RequestMapping(value = _CONFIRM_URI + "{oid}", method = RequestMethod.POST)
    public String confirm(@PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            final Model model, final RedirectAttributes redirectAttributes) {

        setCompetenceCourseMarkSheet(competenceCourseMarkSheet, model);

        try {
            competenceCourseMarkSheet.confirm(false);

        } catch (Exception de) {
            addErrorMessage(de.getLocalizedMessage(), model);

            return jspPage("read");

        }

        return redirect(READ_URL + competenceCourseMarkSheet.getExternalId(), model, redirectAttributes);
    }

    private static final String _SUBMIT_URI = "/submit/";
    public static final String SUBMIT_URL = CONTROLLER_URL + _SUBMIT_URI;

    @RequestMapping(value = _SUBMIT_URI + "{oid}", method = RequestMethod.POST)
    public String submit(@PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            final Model model, final RedirectAttributes redirectAttributes) {

        setCompetenceCourseMarkSheet(competenceCourseMarkSheet, model);

        try {
            new CompetenceCourseMarkSheetBean(competenceCourseMarkSheet).checkRulesForSubmission();
            competenceCourseMarkSheet.submit(false);

        } catch (Exception de) {
            addErrorMessage(de.getLocalizedMessage(), model);

            return jspPage("read");

        }

        return redirect(READ_URL + competenceCourseMarkSheet.getExternalId(), model, redirectAttributes);
    }

    private static final String _REVERT_TO_EDITION_URI = "/reverttoedition/";
    public static final String REVERT_TO_EDITION_URL = CONTROLLER_URL + _REVERT_TO_EDITION_URI;

    @RequestMapping(value = _REVERT_TO_EDITION_URI + "{oid}", method = RequestMethod.POST)
    public String revertToEdition(@PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            final Model model, final RedirectAttributes redirectAttributes) {

        setCompetenceCourseMarkSheet(competenceCourseMarkSheet, model);

        try {
            //TODO: add reason
            competenceCourseMarkSheet.revertToEdition(false, null);

        } catch (Exception de) {
            addErrorMessage(de.getLocalizedMessage(), model);

            return jspPage("read");

        }

        return redirect(READ_URL + competenceCourseMarkSheet.getExternalId(), model, redirectAttributes);
    }

    private static final String _EXPORT_EXCEL_URI = "/exportexcel/";
    public static final String EXPORT_EXCEL_URL = CONTROLLER_URL + _EXPORT_EXCEL_URI;

    @RequestMapping(value = _EXPORT_EXCEL_URI + "{oid}", method = RequestMethod.GET)
    public void exportExcel(@PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            final Model model, final HttpServletResponse response) throws IOException {

        final CompetenceCourse competenceCourse = competenceCourseMarkSheet.getCompetenceCourse();
        final String filename = competenceCourse.getCode() + "_"
                + competenceCourse.getName().replace(' ', '_').replace('/', '-').replace('\\', '-')
                + competenceCourseMarkSheet.getEvaluationDate().toString("yyyy-MM-dd")
                + MarkSheetImportExportService.XLSX_EXTENSION;

        writeFile(response, filename, MarkSheetImportExportService.XLSX_MIME_TYPE, MarkSheetImportExportService
                .exportToXLSX(new CompetenceCourseMarkSheetBean(competenceCourseMarkSheet)));
    }

    private static final String _IMPORT_EXCEL_URI = "/importexcel/";
    public static final String IMPORT_EXCEL_URL = CONTROLLER_URL + _IMPORT_EXCEL_URI;

    @RequestMapping(value = _IMPORT_EXCEL_URI + "{oid}", method = RequestMethod.POST)
    public String importExcel(@PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            @RequestParam(value = "file", required = true) MultipartFile markSheetFile, final Model model,
            final RedirectAttributes redirectAttributes) throws IOException {

        CompetenceCourseMarkSheetBean bean = null;
        try {
            bean = MarkSheetImportExportService.importFromXLSX(competenceCourseMarkSheet,
                    FilenameUtils.getName(markSheetFile.getOriginalFilename()), markSheetFile.getBytes());
            bean.updateEnrolmentEvaluations();

            addInfoMessage(
                    ULisboaSpecificationsUtil.bundle("label.event.evaluation.manageMarkSheet.importExcel.success"),
                    model);

        } catch (Exception e) {
            addErrorMessage(e.getLocalizedMessage(), model);
        }

        setCompetenceCourseMarkSheet(competenceCourseMarkSheet, model);
        setCompetenceCourseMarkSheetBean(
                bean == null ? new CompetenceCourseMarkSheetBean(competenceCourseMarkSheet) : bean, model);

        return jspPage("updateevaluations");

    }

    private static final String _SEARCH_CHANGE_REQUESTS_URI = "/searchchangerequests/";
    public static final String SEARCH_CHANGE_REQUESTS_URL = CONTROLLER_URL + _SEARCH_CHANGE_REQUESTS_URI;

    @RequestMapping(value = _SEARCH_CHANGE_REQUESTS_URI + "{oid}", method = RequestMethod.GET)
    public String searchChangeRequests(
            @PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet, final Model model,
            final RedirectAttributes redirectAttributes) throws IOException {

        setCompetenceCourseMarkSheetBean(new CompetenceCourseMarkSheetBean(competenceCourseMarkSheet), model);
        setCompetenceCourseMarkSheet(competenceCourseMarkSheet, model);

        return jspPage("searchchangerequests");
    }

    private static final String _AUTHORIZE_CHANGE_REQUEST_URI = "/authorizechangerequest/";
    public static final String AUTHORIZE_CHANGE_REQUEST_URL = CONTROLLER_URL + _AUTHORIZE_CHANGE_REQUEST_URI;

    @RequestMapping(value = _AUTHORIZE_CHANGE_REQUEST_URI + "{oid}/{changeRequestId}", method = RequestMethod.POST)
    public String authorizeChangeRequest(
            @PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            @PathVariable("changeRequestId") final CompetenceCourseMarkSheetChangeRequest changeRequest,
            @RequestParam(value = "bean", required = false) final CompetenceCourseMarkSheetBean bean,
            final Model model, final RedirectAttributes redirectAttributes) throws IOException {

        setCompetenceCourseMarkSheet(competenceCourseMarkSheet, model);

        try {

            changeRequest.authorize(Authenticate.getUser().getPerson(), bean.getChangeRequestComments(),
                    bean.getExpireDate());

            return redirect(SEARCH_CHANGE_REQUESTS_URL + getCompetenceCourseMarkSheet(model).getExternalId(), model,
                    redirectAttributes);
        } catch (Exception de) {
            addErrorMessage(de.getLocalizedMessage(), model);
            this.setCompetenceCourseMarkSheetBean(bean, model);

            return jspPage("searchchangerequests");
        }
    }

    private static final String _CLOSE_CHANGE_REQUESTS_URI = "/closechangerequest/";
    public static final String CLOSE_CHANGE_REQUESTS_URL = CONTROLLER_URL + _CLOSE_CHANGE_REQUESTS_URI;

    @RequestMapping(value = _CLOSE_CHANGE_REQUESTS_URI + "{oid}/{changeRequestId}", method = RequestMethod.POST)
    public String closeChangeRequest(@PathVariable("oid") final CompetenceCourseMarkSheet competenceCourseMarkSheet,
            @PathVariable("changeRequestId") final CompetenceCourseMarkSheetChangeRequest changeRequest,
            @RequestParam(value = "bean", required = false) final CompetenceCourseMarkSheetBean bean,
            final Model model, final RedirectAttributes redirectAttributes) throws IOException {

        setCompetenceCourseMarkSheet(competenceCourseMarkSheet, model);

        try {

            changeRequest.close(Authenticate.getUser().getPerson(), bean.getChangeRequestComments());

            return redirect(SEARCH_CHANGE_REQUESTS_URL + getCompetenceCourseMarkSheet(model).getExternalId(), model,
                    redirectAttributes);
        } catch (Exception de) {
            addErrorMessage(de.getLocalizedMessage(), model);
            this.setCompetenceCourseMarkSheetBean(bean, model);

            return jspPage("searchchangerequests");
        }
    }

    private byte[] exportReportToXLS(final CompetenceCourseMarkSheetBean bean) {

        final List<CompetenceCourseSeasonReport> entries = MarkSheetStatusReportService
                .getReportsForCompetenceCourses(bean.getExecutionSemester(), bean.getEvaluationSeasonsToReport());

        final SpreadsheetBuilder builder = new SpreadsheetBuilder();
        builder.addSheet(reportLabelFor("sheetTitle"), new SheetData<CompetenceCourseSeasonReport>(entries) {
            @Override
            protected void makeLine(CompetenceCourseSeasonReport entry) {
                addCell(reportLabelFor("period"), entry.getExecutionSemester().getQualifiedName());
                addCell(reportLabelFor("curricularCourseCode"), entry.getCompetenceCourse().getCode());
                addCell(reportLabelFor("curricularCourseName"), entry.getCompetenceCourse().getName());
                addCell(reportLabelFor("executionCourses"), entry.getExecutionCourses());
                addCell(reportLabelFor("season"),
                        EvaluationSeasonServices.getDescriptionI18N(entry.getSeason()).getContent());
                addCell(reportLabelFor("totalStudents"), entry.getTotalStudents());
                addCell(reportLabelFor("notEvaluatedStudents"), entry.getNotEvaluatedStudents());
                addCell(reportLabelFor("evaluatedStudents"), entry.getEvaluatedStudents());
                addCell(reportLabelFor("marksheetsTotal"), entry.getMarksheetsTotal());
                addCell(reportLabelFor("marksheetsToConfirm"), entry.getMarksheetsToConfirm());
                addCell(reportLabelFor("responsibleName"), Joiner.on("; ").join(entry.getResponsibleNames()));
                addCell(reportLabelFor("responsibleContact"), Joiner.on("; ").join(entry.getResponsibleEmails()));
            }
        });

        final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            builder.build(WorkbookExportFormat.EXCEL, byteArrayOutputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return byteArrayOutputStream.toByteArray();
    }

    static private String reportLabelFor(final String field) {
        return BundleUtil.getString(ULisboaConstants.BUNDLE, "label.MarksheetStatusReport.report." + field);
    }

    @RequestMapping(value = "/exportreport", method = RequestMethod.POST, produces = "text/plain;charset=UTF-8")
    public @ResponseBody ResponseEntity<String> exportReport(
            @RequestParam(value = "bean", required = false) final CompetenceCourseMarkSheetBean bean,
            final Model model) {

        final String reportId = UUID.randomUUID().toString();
        new Thread(() -> processReport(this::exportReportToXLS, bean, reportId)).start();

        return new ResponseEntity<String>(reportId, HttpStatus.OK);
    }

    @Atomic(mode = TxMode.READ)
    protected void processReport(final Function<CompetenceCourseMarkSheetBean, byte[]> reportProcessor,
            final CompetenceCourseMarkSheetBean bean, final String reportId) {

        byte[] content = null;
        try {
            content = reportProcessor.apply(bean);
        } catch (Throwable e) {
            content = createXLSWithError((e instanceof ULisboaSpecificationsDomainException)
                    ? ((ULisboaSpecificationsDomainException) e).getLocalizedMessage()
                    : ExceptionUtils.getFullStackTrace(e));
        }

        ULisboaSpecificationsTemporaryFile.create(reportId, content, Authenticate.getUser());
    }

    private byte[] createXLSWithError(String error) {

        try {

            final SpreadsheetBuilder builder = new SpreadsheetBuilder();
            builder.addSheet("Registrations", new SheetData<String>(Collections.singleton(error)) {
                @Override
                protected void makeLine(String item) {
                    addCell(ULisboaSpecificationsUtil.bundle("label.unexpected.error.occured"), item);
                }
            });

            final ByteArrayOutputStream result = new ByteArrayOutputStream();
            builder.build(WorkbookExportFormat.EXCEL, result);

            return result.toByteArray();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @RequestMapping(value = "/exportstatus/{reportId}", method = RequestMethod.GET, produces = "text/plain;charset=UTF-8")
    public @ResponseBody ResponseEntity<String> exportStatus(
            @PathVariable(value = "reportId") final String reportId, final Model model) {
        return new ResponseEntity<String>(String.valueOf(ULisboaSpecificationsTemporaryFile
                .findByUserAndFilename(Authenticate.getUser(), reportId).isPresent()), HttpStatus.OK);
    }

    @RequestMapping(value = "/downloadreport/{reportId}", method = RequestMethod.GET)
    public void downloadReport(
            @RequestParam(value = "bean", required = false) final CompetenceCourseMarkSheetBean bean,
            @PathVariable("reportId") String reportId, final Model model, RedirectAttributes redirectAttributes,
            HttpServletResponse response) throws IOException {
        final Optional<ULisboaSpecificationsTemporaryFile> temporaryFile = ULisboaSpecificationsTemporaryFile
                .findByUserAndFilename(Authenticate.getUser(), reportId);
        writeFile(response, getFileName(null/*TODO legidio bean.getExecutionSemester()*/),
                "application/vnd.ms-excel", temporaryFile.get().getContent());
    }

    private String getFileName(final ExecutionSemester executionInterval) {
        final org.fenixedu.academic.domain.organizationalStructure.Unit institutionUnit = Bennu.getInstance()
                .getInstitutionUnit();
        final String acronym = institutionUnit.getAcronym();

        final String title = acronym + "_"
                + ULisboaSpecificationsUtil.bundle("label.MarkSheetStatusReport.create").replace(" ", "-") + "_";

        final String period = executionInterval == null ? ""
                : executionInterval.getQualifiedName().replace("/", "-").replace(" ", "-") + "_";

        return title + period + new DateTime().toString("yyyy-MM-dd_HH-mm-ss") + ".xls";
    }

}