/** * 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.serviceRequests; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.HashSet; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.fenixedu.academic.domain.accessControl.academicAdministration.AcademicAccessRule; import org.fenixedu.academic.domain.accessControl.academicAdministration.AcademicOperationType; import org.fenixedu.academic.domain.administrativeOffice.AdministrativeOffice; import org.fenixedu.academic.domain.exceptions.DomainException; import org.fenixedu.academic.domain.serviceRequests.AcademicServiceRequest; import org.fenixedu.academic.domain.serviceRequests.IProgramConclusionRequest; import org.fenixedu.academic.domain.serviceRequests.RectorateSubmissionBatch; import org.fenixedu.academic.domain.serviceRequests.RectorateSubmissionState; import org.fenixedu.academic.domain.serviceRequests.RegistryCode; import org.fenixedu.academic.domain.serviceRequests.documentRequests.DocumentRequest; import org.fenixedu.academic.domain.serviceRequests.documentRequests.IDocumentRequest; import org.fenixedu.academic.ui.struts.action.academicAdministration.AcademicAdministrationApplication.AcademicAdminServicesApp; import org.fenixedu.academic.ui.struts.action.base.FenixDispatchAction; import org.fenixedu.academic.util.Bundle; import org.fenixedu.bennu.core.i18n.BundleUtil; import org.fenixedu.bennu.struts.annotations.Forward; import org.fenixedu.bennu.struts.annotations.Forwards; import org.fenixedu.bennu.struts.annotations.Mapping; import org.fenixedu.bennu.struts.portal.EntryPoint; import org.fenixedu.bennu.struts.portal.StrutsFunctionality; import org.fenixedu.commons.spreadsheet.SheetData; import org.fenixedu.commons.spreadsheet.SpreadsheetBuilder; import org.fenixedu.commons.spreadsheet.WorkbookExportFormat; import pt.ist.fenixframework.Atomic; @StrutsFunctionality(app = AcademicAdminServicesApp.class, path = "rectorate-submission", titleKey = "link.rectorateSubmission", accessGroup = "academic(SERVICE_REQUESTS_RECTORAL_SENDING)") @Mapping(path = "/rectorateDocumentSubmission", module = "academicAdministration") @Forwards({ @Forward(name = "index", path = "/academicAdminOffice/rectorateDocumentSubmission/batchIndex.jsp"), @Forward(name = "viewBatch", path = "/academicAdminOffice/rectorateDocumentSubmission/showBatch.jsp") }) public class RectorateDocumentSubmissionDispatchAction extends FenixDispatchAction { @EntryPoint public ActionForward index(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { Set<AdministrativeOffice> offices = AcademicAccessRule.getOfficesAccessibleToFunction(AcademicOperationType.SERVICE_REQUESTS_RECTORAL_SENDING, getLoggedPerson(request).getUser()).collect(Collectors.toSet()); request.setAttribute("unsent", RectorateSubmissionBatch.getRectorateSubmissionBatchesByState(offices, RectorateSubmissionState.UNSENT)); request.setAttribute("closed", RectorateSubmissionBatch.getRectorateSubmissionBatchesByState(offices, RectorateSubmissionState.CLOSED)); request.setAttribute("sent", RectorateSubmissionBatch.getRectorateSubmissionBatchesByState(offices, RectorateSubmissionState.SENT)); request.setAttribute("received", RectorateSubmissionBatch.getRectorateSubmissionBatchesByState(offices, RectorateSubmissionState.RECEIVED)); return mapping.findForward("index"); } public ActionForward viewBatch(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { RectorateSubmissionBatch batch = getDomainObject(request, "batchOid"); Set<String> actions = new HashSet<String>(); Set<String> confirmActions = new HashSet<String>(); switch (batch.getState()) { case UNSENT: if (!batch.getDocumentRequestSet().isEmpty()) { confirmActions.add("closeBatch"); } break; case CLOSED: actions.add("generateMetadataForRegistry"); actions.add("generateMetadataForDiplomas"); actions.add("zipDocuments"); confirmActions.add("markAsSent"); break; case SENT: actions.add("generateMetadataForDiplomas"); if (batch.allDocumentsReceived()) { confirmActions.add("markAsReceived"); } break; case RECEIVED: break; } request.setAttribute("batch", batch); // Filter out canceled document requests, ticket: #248539 Set<AcademicServiceRequest> requests = new HashSet<AcademicServiceRequest>(); for (AcademicServiceRequest docRequest : batch.getDocumentRequestSet()) { if (!docRequest.isCancelled() && !docRequest.isRejected()) { requests.add(docRequest); } } request.setAttribute("requests", requests); request.setAttribute("actions", actions); request.setAttribute("confirmActions", confirmActions); return mapping.findForward("viewBatch"); } @Atomic public ActionForward closeBatch(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { RectorateSubmissionBatch batch = getDomainObject(request, "batchOid"); batch.closeBatch(); return viewBatch(mapping, actionForm, request, response); } @Atomic public ActionForward markAsSent(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { RectorateSubmissionBatch batch = getDomainObject(request, "batchOid"); batch.markAsSent(); return viewBatch(mapping, actionForm, request, response); } @Atomic public ActionForward markAsReceived(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { RectorateSubmissionBatch batch = getDomainObject(request, "batchOid"); batch.markAsReceived(); return viewBatch(mapping, actionForm, request, response); } public ActionForward generateMetadataForRegistry(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { RectorateSubmissionBatch batch = getDomainObject(request, "batchOid"); Set<AcademicServiceRequest> docs = new HashSet<AcademicServiceRequest>(); for (AcademicServiceRequest document : batch.getDocumentRequestSet()) { // Filter out canceled document requests, ticket: #248539 if (!document.isDiploma() && !document.isCancelled() && !document.isRejected()) { docs.add(document); } } return generateMetadata(docs, "registos-", request, response); } public ActionForward generateMetadataForDiplomas(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { RectorateSubmissionBatch batch = getDomainObject(request, "batchOid"); Set<AcademicServiceRequest> docs = new HashSet<AcademicServiceRequest>(); for (AcademicServiceRequest document : batch.getDocumentRequestSet()) { // Filter out canceled document requests, ticket: #248539 if (document.isDiploma() && !document.isCancelled() && !document.isRejected()) { docs.add(document); } } return generateMetadata(docs, "cartas-", request, response); } private ActionForward generateMetadata(Set<AcademicServiceRequest> documents, String prefix, HttpServletRequest request, HttpServletResponse response) { SortedSet<AcademicServiceRequest> sorted = new TreeSet<AcademicServiceRequest>(DocumentRequest.COMPARATOR_BY_REGISTRY_NUMBER); sorted.addAll(documents); Set<RegistryCode> codes = new HashSet<RegistryCode>(); for (AcademicServiceRequest document : documents) { codes.add(document.getRegistryCode()); } SheetData<AcademicServiceRequest> data = new SheetData<AcademicServiceRequest>(sorted) { @Override protected void makeLine(AcademicServiceRequest academicServiceRequest) { IDocumentRequest document = (IDocumentRequest) academicServiceRequest; addCell("Código", document.getRegistryCode().getCode()); addCell("Tipo de Documento", BundleUtil.getString(Bundle.ENUMERATION, document.getDocumentRequestType().name())); addCell("Apuramento", document instanceof IProgramConclusionRequest ? ((IProgramConclusionRequest) document) .getProgramConclusion().getName().getContent() : null); if (document.isRequestForRegistration()) { addCell("Tipo de Curso", ((DocumentRequest) document).getDegreeType().getName().getContent()); } else if (document.isRequestForPhd()) { addCell("Tipo de Curso", BundleUtil.getString(Bundle.PHD, "label.php.program")); } addCell("Nº de Aluno", document.getStudent().getNumber()); addCell("Nome", document.getPerson().getName()); if (!document.isDiploma()) { addCell("Ficheiro", document.getLastGeneratedDocument().getFilename()); } } }; try { response.setContentType("application/vnd.ms-excel"); response.setHeader("Content-disposition", "attachment; filename=" + prefix + "-" + "(" + codes.size() + ")" + ".xls"); final ServletOutputStream writer = response.getOutputStream(); new SpreadsheetBuilder().addSheet("lote", data).build(WorkbookExportFormat.EXCEL, writer); writer.flush(); response.flushBuffer(); } catch (IOException e) { throw new DomainException("error.rectorateSubmission.errorGeneratingMetadata", e); } return null; } public ActionForward zipDocuments(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { try { RectorateSubmissionBatch batch = getDomainObject(request, "batchOid"); Set<AcademicServiceRequest> requestsToZip = new HashSet<AcademicServiceRequest>(); for (AcademicServiceRequest document : batch.getDocumentRequestSet()) { // Filter out canceled document requests, ticket: #248539 if (!document.isDiploma() && !document.isCancelled() && !document.isRejected()) { requestsToZip.add(document); } } if (!requestsToZip.isEmpty()) { ByteArrayOutputStream bout = new ByteArrayOutputStream(); ZipOutputStream zip = new ZipOutputStream(bout); for (AcademicServiceRequest document : requestsToZip) { zip.putNextEntry(new ZipEntry(document.getLastGeneratedDocument().getFilename())); zip.write(document.getLastGeneratedDocument().getContent()); zip.closeEntry(); } zip.close(); response.setContentType("application/zip"); response.addHeader("Content-Disposition", "attachment; filename=documentos-" + batch.getRange() + ".zip"); ServletOutputStream writer = response.getOutputStream(); writer.write(bout.toByteArray()); writer.flush(); writer.close(); response.flushBuffer(); return null; } else { addActionMessage(request, "error.rectorateSubmission.noDocumentsToZip"); request.setAttribute("batchOid", batch.getExternalId()); return viewBatch(mapping, actionForm, request, response); } } catch (IOException e) { throw new DomainException("error.rectorateSubmission.errorGeneratingMetadata", e); } } @Atomic public ActionForward delayRequest(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { AcademicServiceRequest document = getDomainObject(request, "academicServiceRequestOid"); request.setAttribute("batchOid", document.getRectorateSubmissionBatch().getExternalId()); if (document.isPiggyBackedOnRegistry()) { addActionMessage(request, "error.rectorateSubmissionBatch.cannotDelayPiggyBackedDocument"); } else { RectorateSubmissionBatch target = document.getRectorateSubmissionBatch(); while (!target.isUnsent()) { target = target.getNextRectorateSubmissionBatch(); } document.setRectorateSubmissionBatch(target); } return viewBatch(mapping, actionForm, request, response); } }