/** * 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.phd.candidacy.publicProgram.institution; import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Arrays; import java.util.Collections; import java.util.List; 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.Person; import org.fenixedu.academic.domain.PublicCandidacyHashCode; import org.fenixedu.academic.domain.QualificationBean; import org.fenixedu.academic.domain.exceptions.DomainException; import org.fenixedu.academic.domain.organizationalStructure.Unit; import org.fenixedu.academic.domain.phd.PhdIndividualProgramDocumentType; import org.fenixedu.academic.domain.phd.PhdIndividualProgramProcess; import org.fenixedu.academic.domain.phd.PhdIndividualProgramProcess.PublicPhdIndividualProgramProcess; import org.fenixedu.academic.domain.phd.PhdIndividualProgramProcessBean; import org.fenixedu.academic.domain.phd.PhdParticipantBean; import org.fenixedu.academic.domain.phd.PhdParticipantBean.PhdParticipantType; import org.fenixedu.academic.domain.phd.PhdProgramCandidacyProcessState; import org.fenixedu.academic.domain.phd.PhdProgramDocumentUploadBean; import org.fenixedu.academic.domain.phd.PhdProgramProcessDocument; import org.fenixedu.academic.domain.phd.candidacy.InstitutionPhdCandidacyPeriod; import org.fenixedu.academic.domain.phd.candidacy.PhdCandidacyPeriod; import org.fenixedu.academic.domain.phd.candidacy.PhdCandidacyReferee; import org.fenixedu.academic.domain.phd.candidacy.PhdCandidacyRefereeBean; import org.fenixedu.academic.domain.phd.candidacy.PhdCandidacyRefereeLetter; import org.fenixedu.academic.domain.phd.candidacy.PhdCandidacyRefereeLetterBean; import org.fenixedu.academic.domain.phd.candidacy.PhdProgramCandidacyProcess; import org.fenixedu.academic.domain.phd.candidacy.PhdProgramCandidacyProcessBean; import org.fenixedu.academic.domain.phd.candidacy.PhdProgramPublicCandidacyHashCode; import org.fenixedu.academic.domain.phd.individualProcess.activities.AddAssistantGuidingInformation; import org.fenixedu.academic.domain.phd.individualProcess.activities.AddCandidacyReferees; import org.fenixedu.academic.domain.phd.individualProcess.activities.AddGuidingsInformation; import org.fenixedu.academic.domain.phd.individualProcess.activities.AddQualification; import org.fenixedu.academic.domain.phd.individualProcess.activities.DeleteAssistantGuiding; import org.fenixedu.academic.domain.phd.individualProcess.activities.DeleteGuiding; import org.fenixedu.academic.domain.phd.individualProcess.activities.EditIndividualProcessInformation; import org.fenixedu.academic.domain.phd.individualProcess.activities.EditPersonalInformation; import org.fenixedu.academic.domain.phd.individualProcess.activities.RemoveCandidacyReferee; import org.fenixedu.academic.domain.phd.individualProcess.activities.UploadDocuments; import org.fenixedu.academic.domain.phd.individualProcess.activities.ValidatedByCandidate; import org.fenixedu.academic.dto.person.PersonBean; import org.fenixedu.academic.dto.person.PhotographUploadBean; import org.fenixedu.academic.dto.person.PhotographUploadBean.UnableToProcessTheImage; import org.fenixedu.academic.service.services.caseHandling.CreateNewProcess; import org.fenixedu.academic.service.services.caseHandling.ExecuteProcessActivity; import org.fenixedu.academic.service.services.fileManager.UploadOwnPhoto; import org.fenixedu.academic.service.services.person.qualification.DeleteQualification; import org.fenixedu.academic.ui.struts.action.phd.candidacy.publicProgram.PublicPhdProgramCandidacyProcessDA; import org.fenixedu.academic.ui.struts.action.publico.PublicApplication.PublicPhdApp; import org.fenixedu.academic.util.Bundle; import org.fenixedu.academic.util.ContentType; import org.fenixedu.academic.util.phd.InstitutionPhdCandidacyProcessProperties; 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.i18n.I18N; import org.joda.time.DateTime; import pt.ist.fenixWebFramework.renderers.components.state.IViewState; import pt.ist.fenixWebFramework.renderers.utils.RenderUtils; @StrutsFunctionality(app = PublicPhdApp.class, path = "candidacy", titleKey = "title.public.phd.program.candidacy") @Mapping(path = "/applications/phd/phdProgramApplicationProcess", module = "publico") @Forwards({ @Forward(name = "outOfCandidacyPeriod", path = "/phd/candidacy/publicProgram/institution/outOfCandidacyPeriod.jsp"), @Forward(name = "createIdentification", path = "/phd/candidacy/publicProgram/institution/createIdentification.jsp"), @Forward(name = "createIdentificationSuccess", path = "/phd/candidacy/publicProgram/institution/createIdentificationSuccess.jsp"), @Forward(name = "applicationSubmissionGuide", path = "/phd/candidacy/publicProgram/institution/applicationSubmissionGuide.jsp"), @Forward(name = "fillPersonalData", path = "/phd/candidacy/publicProgram/institution/fillPersonalData.jsp"), @Forward(name = "fillPhdProgramData", path = "/phd/candidacy/publicProgram/institution/fillPhdProgramData.jsp"), @Forward(name = "applicationCreationReport", path = "/phd/candidacy/publicProgram/institution/applicationCreationReport.jsp"), @Forward(name = "view", path = "/phd/candidacy/publicProgram/institution/view.jsp"), @Forward(name = "editPersonalData", path = "/phd/candidacy/publicProgram/institution/editPersonalData.jsp"), @Forward(name = "editPhdInformationData", path = "/phd/candidacy/publicProgram/institution/editPhdInformationData.jsp"), @Forward(name = "editQualifications", path = "/phd/candidacy/publicProgram/institution/editQualifications.jsp"), @Forward(name = "uploadDocuments", path = "/phd/candidacy/publicProgram/institution/uploadDocuments.jsp"), @Forward(name = "editReferees", path = "/phd/candidacy/publicProgram/institution/editReferees.jsp"), @Forward(name = "createRefereeLetter", path = "/phd/candidacy/publicProgram/institution/createRefereeLetter.jsp"), @Forward(name = "createRefereeLetterSuccess", path = "/phd/candidacy/publicProgram/institution/createRefereeLetterSuccess.jsp"), @Forward(name = "editGuidings", path = "/phd/candidacy/publicProgram/institution/editGuidings.jsp"), @Forward(name = "validateApplication", path = "/phd/candidacy/publicProgram/institution/validateApplication.jsp"), @Forward(name = "uploadPhoto", path = "/phd/candidacy/publicProgram/institution/uploadPhoto.jsp"), @Forward(name = "identificationRecovery", path = "/phd/candidacy/publicProgram/institution/identificationRecovery.jsp"), @Forward(name = "emailSentForIdentificationRecovery", path = "/phd/candidacy/publicProgram/institution/emailSentForIdentificationRecovery.jsp") }) public class PublicInstitutionPhdProgramsCandidacyProcessDA extends PublicPhdProgramCandidacyProcessDA { static private final List<String> DO_NOT_VALIDATE_CANDIDACY_PERIOD_IN_METHODS = Arrays.asList( "viewCandidacy", "backToViewCandidacy", "prepareCreateRefereeLetter", "createRefereeLetterInvalid", "createRefereeLetter"); @Override protected ActionForward filterDispatchMethod(final PhdProgramCandidacyProcessBean bean, ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws Exception { final PhdProgramPublicCandidacyHashCode hashCode = (bean != null ? bean.getCandidacyHashCode() : null); final String methodName = getMethodName(mapping, actionForm, request, response, mapping.getParameter()); if (methodName == null || !DO_NOT_VALIDATE_CANDIDACY_PERIOD_IN_METHODS.contains(methodName)) { if (isOutOfCandidacyPeriod(hashCode)) { InstitutionPhdCandidacyPeriod nextCandidacyPeriod = InstitutionPhdCandidacyPeriod.readNextCandidacyPeriod(); request.setAttribute("candidacyPeriod", getPhdCandidacyPeriod(hashCode)); request.setAttribute("nextCandidacyPeriod", nextCandidacyPeriod); return mapping.findForward("outOfCandidacyPeriod"); } } return null; } private boolean isOutOfCandidacyPeriod(final PhdProgramPublicCandidacyHashCode hashCode) { PhdCandidacyPeriod phdCandidacyPeriod = getPhdCandidacyPeriod(hashCode); return phdCandidacyPeriod == null || !phdCandidacyPeriod.contains(new DateTime()); } private PhdCandidacyPeriod getPhdCandidacyPeriod(final PhdProgramPublicCandidacyHashCode hashCode) { final DateTime date = (hashCode != null && hashCode.hasCandidacyProcess()) ? hashCode.getPhdProgramCandidacyProcess() .getCandidacyDate().toDateTimeAtCurrentTime() : new DateTime(); return InstitutionPhdCandidacyPeriod.readInstitutionPhdCandidacyPeriodForDate(date); } /* * Create application identification for submission with email */ @EntryPoint public ActionForward prepareCreateIdentification(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final String hash = request.getParameter("hash"); final PhdProgramPublicCandidacyHashCode hashCode = (PhdProgramPublicCandidacyHashCode) PublicCandidacyHashCode.getPublicCandidacyCodeByHash(hash); if (hashCode != null) { return viewCandidacy(mapping, form, request, response, hashCode); } request.setAttribute("candidacyBean", new PhdProgramCandidacyProcessBean()); return mapping.findForward("createIdentification"); } public ActionForward createIdentificationInvalid(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { request.setAttribute("candidacyBean", getRenderedObject("candidacyBean")); return mapping.findForward("createIdentification"); } public ActionForward createIdentification(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcessBean bean = getCandidacyBean(); if (bean == null) { return prepareCreateIdentification(mapping, form, request, response); } final PhdProgramPublicCandidacyHashCode hashCode = PhdProgramPublicCandidacyHashCode.getOrCreatePhdProgramCandidacyHashCode(bean.getEmail()); if (hashCode.hasCandidacyProcess() && hashCode.getPhdProgramCandidacyProcess().getCandidacy().getDegreeCurricularPlan() .equals(bean.getProcess().getCandidacy().getDegreeCurricularPlan())) { addErrorMessage(request, "error.PhdProgramPublicCandidacyHashCode.already.has.candidacy"); return prepareCreateIdentification(mapping, form, request, response); } sendSubmissionEmailForCandidacy(hashCode, request); String url = String.format("%s?hash=%s", InstitutionPhdCandidacyProcessProperties.getPublicCandidacySubmissionLink(I18N.getLocale()), hashCode.getValue()); request.setAttribute("processLink", url); return mapping.findForward("createIdentificationSuccess"); } private void sendSubmissionEmailForCandidacy(final PublicCandidacyHashCode hashCode, final HttpServletRequest request) { final String subject = BundleUtil.getString(Bundle.PHD, "message.phd.institution.application.email.subject.send.link.to.submission", Unit.getInstitutionAcronym()); final String body = BundleUtil.getString(Bundle.PHD, "message.phd.institution.email.body.send.link.to.submission", Unit.getInstitutionAcronym()); hashCode.sendEmail(subject, String.format(body, InstitutionPhdCandidacyProcessProperties.getPublicCandidacySubmissionLink(I18N.getLocale()), hashCode.getValue())); } /* * Identification recovery */ public ActionForward prepareIdentificationRecovery(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { request.setAttribute("candidacyBean", new PhdProgramCandidacyProcessBean()); return mapping.findForward("identificationRecovery"); } public ActionForward identificationRecoveryInvalid(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { request.setAttribute("candidacyBean", getCandidacyBean()); return mapping.findForward("identificationRecovery"); } public ActionForward identificationRecovery(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcessBean bean = getCandidacyBean(); final PhdProgramPublicCandidacyHashCode hashCode = PhdProgramPublicCandidacyHashCode.getPhdProgramCandidacyHashCode(bean.getEmail(), bean.getProgram()); if (hashCode != null) { if (hashCode.hasCandidacyProcess()) { sendRecoveryEmailForCandidate(hashCode, request); } else { sendSubmissionEmailForCandidacy(hashCode, request); } } return mapping.findForward("emailSentForIdentificationRecovery"); } private void sendRecoveryEmailForCandidate(PhdProgramPublicCandidacyHashCode candidacyHashCode, HttpServletRequest request) { final String subject = BundleUtil.getString(Bundle.PHD, "message.phd.email.subject.recovery.access", Unit.getInstitutionAcronym()); final String body = BundleUtil.getString(Bundle.PHD, "message.phd.institution.email.body.recovery.access", Unit.getInstitutionAcronym()); candidacyHashCode.sendEmail(subject, String.format(body, InstitutionPhdCandidacyProcessProperties.getPublicCandidacyAccessLink(I18N.getLocale()), candidacyHashCode.getValue())); } /* * Submission forms */ public ActionForward beginSubmission(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { return mapping.findForward("applicationSubmissionGuide"); } public ActionForward prepareFillPersonalData(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramPublicCandidacyHashCode hashCode = (PhdProgramPublicCandidacyHashCode) PublicCandidacyHashCode.getPublicCandidacyCodeByHash(request .getParameter("hash")); if (hashCode == null) { return prepareCreateIdentification(mapping, form, request, response); } if (hashCode.hasCandidacyProcess()) { return viewCandidacy(mapping, form, request, response, hashCode); } final PhdProgramCandidacyProcessBean bean = new PhdProgramCandidacyProcessBean(); PhdCandidacyPeriod phdCandidacyPeriod = getPhdCandidacyPeriod(hashCode); bean.setPersonBean(new PersonBean()); bean.getPersonBean().setEmail(hashCode.getEmail()); bean.setCandidacyHashCode(hashCode); bean.setExecutionYear(phdCandidacyPeriod.getExecutionInterval()); bean.setState(PhdProgramCandidacyProcessState.PRE_CANDIDATE); bean.setMigratedProcess(Boolean.FALSE); bean.setPhdCandidacyPeriod(phdCandidacyPeriod); request.setAttribute("candidacyBean", bean); return mapping.findForward("fillPersonalData"); } @Override public ActionForward fillPersonalDataInvalid(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { request.setAttribute("candidacyBean", getCandidacyBean()); return mapping.findForward("fillPersonalData"); } private ActionForward returnToPersonalData(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { request.setAttribute("candidacyBean", getCandidacyBean()); return mapping.findForward("fillPersonalData"); } private ActionForward prepareFillPhdProgramData(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { request.setAttribute("candidacyBean", getCandidacyBean()); return mapping.findForward("fillPhdProgramData"); } private ActionForward fillPhdProgramDataInvalid(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { request.setAttribute("candidacyBean", getCandidacyBean()); return mapping.findForward("fillPhdProgramData"); } private ActionForward fillPhdProgramDataPostback(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { request.setAttribute("candidacyBean", getCandidacyBean()); return mapping.findForward("fillPhdProgramData"); } public ActionForward createApplication(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { ActionForward checkPersonalDataForward = checkPersonalData(mapping, form, request, response); if (checkPersonalDataForward != null) { return checkPersonalDataForward; } final PhdProgramCandidacyProcessBean bean = getCandidacyBean(); if (PhdProgramPublicCandidacyHashCode.getPhdProgramCandidacyHashCode(bean.getCandidacyHashCode().getEmail(), bean.getProgram()) != null) { addErrorMessage(request, "error.PhdProgramPublicCandidacyHashCode.already.has.candidacy"); return fillPersonalDataInvalid(mapping, form, request, response); } PhdIndividualProgramProcess process = (PhdIndividualProgramProcess) CreateNewProcess.run(PublicPhdIndividualProgramProcess.class, bean); sendApplicationSuccessfullySubmitedEmail(bean.getCandidacyHashCode(), request); request.setAttribute("phdIndividualProgramProcess", process); request.setAttribute("candidacyHashCode", bean.getCandidacyHashCode()); PhdProgramPublicCandidacyHashCode candidacyProcessHashCode = process.getCandidacyProcessHashCode(); String processLink = InstitutionPhdCandidacyProcessProperties.getPublicCandidacyAccessLink(candidacyProcessHashCode, I18N.getLocale()); request.setAttribute("processLink", processLink); return mapping.findForward("applicationCreationReport"); } private void sendApplicationSuccessfullySubmitedEmail(final PhdProgramPublicCandidacyHashCode hashCode, final HttpServletRequest request) { // TODO: if candidacy period exists, then change body message to send // candidacy limit end date final String subject = BundleUtil.getString(Bundle.PHD, "message.phd.institution.email.subject.application.submited", Unit.getInstitutionAcronym()); final String body = BundleUtil.getString(Bundle.PHD, "message.phd.institution.email.body.application.submited", Unit.getInstitutionAcronym()); hashCode.sendEmail(subject, String.format(body, hashCode.getPhdProgramCandidacyProcess().getProcessNumber(), InstitutionPhdCandidacyProcessProperties.getPublicCandidacyAccessLink(I18N.getLocale()), hashCode.getValue())); } /* * View application */ public ActionForward viewApplication(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { return viewCandidacy(mapping, form, request, response, (PhdProgramPublicCandidacyHashCode) PublicCandidacyHashCode.getPublicCandidacyCodeByHash(request .getParameter("hash"))); } private ActionForward viewCandidacy(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, PhdProgramPublicCandidacyHashCode hashCode) { if (hashCode == null || !hashCode.hasCandidacyProcess()) { return prepareFillPersonalData(mapping, form, request, response); } PhdIndividualProgramProcess individualProgramProcess = hashCode.getIndividualProgramProcess(); request.setAttribute("process", individualProgramProcess.getCandidacyProcess()); canEditCandidacy(request, hashCode); canEditPersonalInformation(request, hashCode.getPerson()); PersonBean personBean = new PersonBean(individualProgramProcess.getPerson()); initPersonBeanUglyHack(personBean, individualProgramProcess.getPerson()); request.setAttribute("personBean", personBean); validateProcess(request, individualProgramProcess); return mapping.findForward("view"); } private boolean validateProcess(final HttpServletRequest request, final PhdIndividualProgramProcess process) { boolean result = true; return validateProcessDocuments(request, process) && result; } private boolean validateProcessDocuments(final HttpServletRequest request, final PhdIndividualProgramProcess process) { boolean result = true; boolean hasPaymentFees = process.getCandidacyProcess().hasPaymentCodeToPay(); request.setAttribute("hasPaymentFees", hasPaymentFees); int totalDocuments = 5; //with payment fees if (!hasPaymentFees) { totalDocuments = 4; } BigDecimal numberOfDocumentsToSubmit = new BigDecimal(totalDocuments + process.getQualifications().size()); BigDecimal numberOfDocumentsSubmitted = new BigDecimal(0); if (!process.hasCandidacyProcessDocument(PhdIndividualProgramDocumentType.ID_DOCUMENT)) { addValidationMessage(request, "message.validation.missing.id.document"); result &= false; } else { numberOfDocumentsSubmitted = numberOfDocumentsSubmitted.add(new BigDecimal(1)); } if (hasPaymentFees) { if (!process.hasCandidacyProcessDocument(PhdIndividualProgramDocumentType.PAYMENT_DOCUMENT)) { addValidationMessage(request, "message.validation.missing.payment.document"); result &= false; } else { numberOfDocumentsSubmitted = numberOfDocumentsSubmitted.add(new BigDecimal(1)); } } if (!process.hasCandidacyProcessDocument(PhdIndividualProgramDocumentType.SOCIAL_SECURITY)) { addValidationMessage(request, "message.validation.missing.social.security.document"); result &= false; } else { numberOfDocumentsSubmitted = numberOfDocumentsSubmitted.add(new BigDecimal(1)); } if (!process.hasCandidacyProcessDocument(PhdIndividualProgramDocumentType.CV)) { addValidationMessage(request, "message.validation.missing.cv"); result &= false; } else { numberOfDocumentsSubmitted = numberOfDocumentsSubmitted.add(new BigDecimal(1)); } if (process.getCandidacyProcessDocumentsCount(PhdIndividualProgramDocumentType.HABILITATION_CERTIFICATE_DOCUMENT) < process .getQualifications().size()) { addValidationMessage(request, "message.validation.missing.qualification.documents", String.valueOf(process.getQualifications().size())); result &= false; } else { numberOfDocumentsSubmitted = numberOfDocumentsSubmitted .add(new BigDecimal( process.getCandidacyProcessDocumentsCount(PhdIndividualProgramDocumentType.HABILITATION_CERTIFICATE_DOCUMENT))); } if (!process.hasCandidacyProcessDocument(PhdIndividualProgramDocumentType.MOTIVATION_LETTER)) { addValidationMessage(request, "message.validation.missing.motivation.letter"); result &= false; } else { numberOfDocumentsSubmitted = numberOfDocumentsSubmitted.add(new BigDecimal(1)); } request.setAttribute( "documentsSubmittedPercentage", numberOfDocumentsSubmitted.divide(numberOfDocumentsToSubmit, 2, RoundingMode.HALF_EVEN) .multiply(new BigDecimal(100)).intValue()); request.setAttribute("numberOfDocumentsToSubmit", numberOfDocumentsToSubmit.intValue()); request.setAttribute("numberOfDocumentsSubmitted", numberOfDocumentsSubmitted.intValue()); return result; } /* * Edit personal data */ public ActionForward prepareEditPersonalData(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); final PhdProgramCandidacyProcessBean bean = new PhdProgramCandidacyProcessBean(process); Person person = process.getPerson(); PersonBean personBean = new PersonBean(person); bean.setPersonBean(personBean); /* TODO: UGLY HACK DUE TO PENDING VALIDATION DATA FOR PERSON */ initPersonBeanUglyHack(personBean, person); canEditCandidacy(request, process.getCandidacyHashCode()); canEditPersonalInformation(request, person); request.setAttribute("candidacyBean", bean); return mapping.findForward("editPersonalData"); } public ActionForward editPersonalDataInvalid(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); PhdProgramCandidacyProcessBean candidacyBean = getCandidacyBean(); request.setAttribute("candidacyBean", candidacyBean); canEditCandidacy(request, process.getCandidacyHashCode()); canEditPersonalInformation(request, process.getPerson()); return mapping.findForward("editPersonalData"); } public ActionForward editPersonalData(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcessBean bean = getCandidacyBean(); PhdProgramCandidacyProcess process = getProcess(request); canEditCandidacy(request, process.getCandidacyHashCode()); canEditPersonalInformation(request, process.getPerson()); try { ExecuteProcessActivity .run(process.getIndividualProgramProcess(), EditPersonalInformation.class, bean.getPersonBean()); } catch (final DomainException e) { addErrorMessage(request, e.getKey(), e.getArgs()); request.setAttribute("candidacyBean", bean); return mapping.findForward("editPersonalData"); } return viewCandidacy(mapping, form, request, response, process.getCandidacyHashCode()); } /* * Edit phd information data */ public ActionForward prepareEditPhdInformationData(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); final PhdProgramCandidacyProcessBean candidacyBean = new PhdProgramCandidacyProcessBean(process); request.setAttribute("candidacyBean", candidacyBean); request.setAttribute("individualProcessBean", new PhdIndividualProgramProcessBean(process.getIndividualProgramProcess())); canEditCandidacy(request, process.getCandidacyHashCode()); return mapping.findForward("editPhdInformationData"); } public ActionForward prepareEditPhdInformationDataFocusAreaPostback(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); PhdProgramCandidacyProcessBean candidacyBean = getCandidacyBean(); final PhdIndividualProgramProcessBean bean = getIndividualProcessBean(); request.setAttribute("candidacyBean", candidacyBean); request.setAttribute("individualProcessBean", bean); canEditCandidacy(request, process.getCandidacyHashCode()); return mapping.findForward("editPhdInformationData"); } public ActionForward editPhdInformationDataInvalid(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); PhdProgramCandidacyProcessBean candidacyBean = getCandidacyBean(); final PhdIndividualProgramProcessBean bean = getIndividualProcessBean(); request.setAttribute("candidacyBean", candidacyBean); request.setAttribute("individualProcessBean", bean); canEditCandidacy(request, process.getCandidacyHashCode()); return mapping.findForward("editPhdInformationData"); } public ActionForward editPhdInformationData(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdIndividualProgramProcessBean bean = getIndividualProcessBean(); PhdProgramCandidacyProcess process = getProcess(request); canEditCandidacy(request, process.getCandidacyHashCode()); try { ExecuteProcessActivity.run(process.getIndividualProgramProcess(), EditIndividualProcessInformation.class, bean); addSuccessMessage(request, "message.phdIndividualProgramProcessInformation.edit.success"); } catch (final DomainException e) { addErrorMessage(request, e.getKey(), e.getArgs()); request.setAttribute("candidacyBean", getCandidacyBean()); request.setAttribute("individualProcessBean", bean); return mapping.findForward("editPhdInformationData"); } return viewCandidacy(mapping, form, request, response, process.getCandidacyHashCode()); } /* * Qualifications */ public ActionForward prepareEditQualifications(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { PhdProgramCandidacyProcess process = getProcess(request); canEditCandidacy(request, process.getCandidacyHashCode()); PhdProgramCandidacyProcessBean bean = new PhdProgramCandidacyProcessBean(process); QualificationBean qualificationBean = new QualificationBean(); request.setAttribute("candidacyBean", bean); request.setAttribute("qualificationBean", qualificationBean); return mapping.findForward("editQualifications"); } public ActionForward editQualificationsInvalid(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { PhdProgramCandidacyProcessBean bean = getCandidacyBean(); QualificationBean qualificationBean = getQualificationBean(); request.setAttribute("candidacyBean", bean); request.setAttribute("qualificationBean", qualificationBean); return prepareEditQualifications(mapping, form, request, response); } public ActionForward addQualification(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { PhdProgramCandidacyProcess process = getProcess(request); canEditCandidacy(request, process.getCandidacyHashCode()); try { ExecuteProcessActivity.run(process.getIndividualProgramProcess(), AddQualification.class, getQualificationBean()); addSuccessMessage(request, "message.qualification.information.create.success"); } catch (final DomainException e) { addErrorMessage(request, e.getKey(), e.getArgs()); return editQualificationsInvalid(mapping, form, request, response); } RenderUtils.invalidateViewState(); return prepareEditQualifications(mapping, form, request, response); } public ActionForward removeQualification(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { PhdProgramCandidacyProcess process = getProcess(request); canEditCandidacy(request, process.getCandidacyHashCode()); try { ExecuteProcessActivity.run(process.getIndividualProgramProcess(), DeleteQualification.class, getDomainObject(request, "qualificationId")); } catch (final DomainException e) { addErrorMessage(request, e.getKey(), e.getArgs()); return editQualificationsInvalid(mapping, form, request, response); } RenderUtils.invalidateViewState(); return prepareEditQualifications(mapping, form, request, response); } /* * Upload documents */ public ActionForward prepareUploadDocuments(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); final PhdProgramCandidacyProcessBean bean = new PhdProgramCandidacyProcessBean(process); canEditCandidacy(request, process.getCandidacyHashCode()); RenderUtils.invalidateViewState(); request.setAttribute("candidacyBean", bean); request.setAttribute("candidacyProcessDocuments", process.getLatestDocumentVersions()); request.setAttribute("hasPaymentFees", process.hasPaymentCodeToPay()); final PhdProgramDocumentUploadBean uploadBean = new PhdProgramDocumentUploadBean(); uploadBean.setIndividualProgramProcess(process.getIndividualProgramProcess()); request.setAttribute("documentByType", uploadBean); validateProcessDocuments(request, process.getIndividualProgramProcess()); return mapping.findForward("uploadDocuments"); } @Override public ActionForward uploadDocumentsInvalid(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); PhdProgramCandidacyProcessBean bean = getCandidacyBean(); PhdProgramDocumentUploadBean uploadBean = getUploadBean(); canEditCandidacy(request, process.getCandidacyHashCode()); request.setAttribute("candidacyProcessDocuments", process.getLatestDocumentVersions()); request.setAttribute("candidacyBean", bean); request.setAttribute("documentByType", uploadBean); validateProcessDocuments(request, process.getIndividualProgramProcess()); return mapping.findForward("uploadDocuments"); } @Override public ActionForward uploadDocuments(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); if (!RenderUtils.getViewState("documentByType").isValid()) { return uploadDocumentsInvalid(mapping, form, request, response); } final PhdProgramDocumentUploadBean uploadBean = getUploadBean(); if (!uploadBean.hasAnyInformation()) { addErrorMessage(request, "message.no.documents.to.upload"); return uploadDocumentsInvalid(mapping, form, request, response); } try { ExecuteProcessActivity.run(process.getIndividualProgramProcess(), UploadDocuments.class, Collections.singletonList(uploadBean)); addSuccessMessage(request, "message.documents.uploaded.with.success"); } catch (final DomainException e) { addErrorMessage(request, "message.no.documents.to.upload"); return uploadDocumentsInvalid(mapping, form, request, response); } return prepareUploadDocuments(mapping, form, request, response); } public ActionForward removeDocument(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); final PhdProgramProcessDocument document = getDomainObject(request, "documentId"); try { ExecuteProcessActivity.run(process, org.fenixedu.academic.domain.phd.candidacy.activities.RemoveCandidacyDocument.class, document); addSuccessMessage(request, "message.documents.uploaded.with.success"); } catch (final DomainException e) { addErrorMessage(request, "message.no.documents.to.upload"); return uploadDocumentsInvalid(mapping, form, request, response); } return prepareUploadDocuments(mapping, form, request, response); } /* * Edit phd referees */ public ActionForward prepareEditReferees(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); final PhdProgramCandidacyProcessBean bean = new PhdProgramCandidacyProcessBean(process); canEditCandidacy(request, process.getCandidacyHashCode()); request.setAttribute("candidacyBean", bean); request.setAttribute("refereeBean", new PhdCandidacyRefereeBean()); return mapping.findForward("editReferees"); } public ActionForward addReferee(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); try { ExecuteProcessActivity.run(process.getIndividualProgramProcess(), AddCandidacyReferees.class, Collections.singletonList(getRenderedObject("refereeBean"))); addSuccessMessage(request, "message.referee.information.create.success"); } catch (final DomainException e) { addErrorMessage(request, e.getKey(), e.getArgs()); return editRefereesInvalid(mapping, form, request, response); } RenderUtils.invalidateViewState(); return prepareEditReferees(mapping, form, request, response); } public ActionForward editRefereesInvalid(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); request.setAttribute("candidacyBean", getCandidacyBean()); request.setAttribute("refereeBean", getPhdCandidacyReferee()); canEditCandidacy(request, process.getCandidacyHashCode()); return mapping.findForward("editReferees"); } public ActionForward sendCandidacyRefereeEmail(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdCandidacyReferee referee = getDomainObject(request, "candidacyRefereeId"); referee.sendEmail(); addSuccessMessage(request, "message.candidacy.referee.email.sent.with.success", referee.getName()); return prepareEditReferees(mapping, form, request, response); } public ActionForward prepareCreateRefereeLetter(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { final PhdCandidacyReferee hashCode = (PhdCandidacyReferee) PublicCandidacyHashCode.getPublicCandidacyCodeByHash(request.getParameter("hash")); request.setAttribute("refereeLetterHash", hashCode); if (hashCode == null) { request.setAttribute("no-information", Boolean.TRUE); return mapping.findForward("createRefereeLetterSuccess"); } if (hashCode.getLetter() != null) { request.setAttribute("has-letter", Boolean.TRUE); request.setAttribute("letter", hashCode.getLetter()); return mapping.findForward("createRefereeLetterSuccess"); } final PhdCandidacyRefereeLetterBean bean = new PhdCandidacyRefereeLetterBean(); bean.setCandidacyReferee(hashCode); bean.setRefereeName(hashCode.getName()); request.setAttribute("createRefereeLetterBean", bean); return mapping.findForward("createRefereeLetter"); } public ActionForward createRefereeLetterInvalid(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdCandidacyReferee hashCode = (PhdCandidacyReferee) PublicCandidacyHashCode.getPublicCandidacyCodeByHash(request.getParameter("hash")); request.setAttribute("refereeLetterHash", hashCode); final PhdCandidacyRefereeLetterBean bean = new PhdCandidacyRefereeLetterBean(); bean.setCandidacyReferee(hashCode); bean.setRefereeName(hashCode.getName()); request.setAttribute("createRefereeLetterBean", bean); return mapping.findForward("createRefereeLetter"); } public ActionForward createRefereeLetter(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { final PhdCandidacyReferee hashCode = (PhdCandidacyReferee) PublicCandidacyHashCode.getPublicCandidacyCodeByHash(request.getParameter("hash")); request.setAttribute("refereeLetterHash", hashCode); final PhdCandidacyRefereeLetterBean bean = getRenderedObject("createRefereeLetterBean"); if (hasAnyRefereeLetterViewStateInvalid()) { return createRefereeLetterInvalid(mapping, actionForm, request, response); } try { PhdCandidacyRefereeLetter.create(bean); } catch (final DomainException e) { addErrorMessage(request, e.getKey(), e.getArgs()); request.setAttribute("createRefereeLetterBean", bean); return mapping.findForward("createRefereeLetter"); } request.setAttribute("created-with-success", Boolean.TRUE); return mapping.findForward("createRefereeLetterSuccess"); } public ActionForward removeReferee(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); final PhdCandidacyReferee referee = getDomainObject(request, "candidacyRefereeId"); try { ExecuteProcessActivity.run(process.getIndividualProgramProcess(), RemoveCandidacyReferee.class, referee); addSuccessMessage(request, "message.referee.information.remove.success"); } catch (final DomainException e) { addErrorMessage(request, e.getKey(), e.getArgs()); return editRefereesInvalid(mapping, form, request, response); } RenderUtils.invalidateViewState(); return prepareEditReferees(mapping, form, request, response); } /* * Edit Phd Guidings */ public ActionForward prepareEditCandidacyGuidings(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); final PhdProgramCandidacyProcessBean bean = new PhdProgramCandidacyProcessBean(process); canEditCandidacy(request, process.getCandidacyHashCode()); request.setAttribute("candidacyBean", bean); PhdParticipantBean guidingBean = new PhdParticipantBean(); guidingBean.setParticipantType(PhdParticipantType.EXTERNAL); PhdProgramDocumentUploadBean guidingAcceptanceLetter = new PhdProgramDocumentUploadBean(); guidingAcceptanceLetter.setType(PhdIndividualProgramDocumentType.GUIDER_ACCEPTANCE_LETTER); guidingBean.setGuidingAcceptanceLetter(guidingAcceptanceLetter); request.setAttribute("guidingBean", guidingBean); PhdParticipantBean assistantGuidingBean = new PhdParticipantBean(); assistantGuidingBean.setParticipantType(PhdParticipantType.EXTERNAL); PhdProgramDocumentUploadBean assistantGuidingAcceptanceLetter = new PhdProgramDocumentUploadBean(); assistantGuidingAcceptanceLetter.setType(PhdIndividualProgramDocumentType.ASSISTENT_GUIDER_ACCEPTANCE_LETTER); assistantGuidingBean.setGuidingAcceptanceLetter(assistantGuidingAcceptanceLetter); request.setAttribute("assistantGuidingBean", assistantGuidingBean); return mapping.findForward("editGuidings"); } public ActionForward addGuiding(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); PhdParticipantBean bean = getGuidingBean(); try { ExecuteProcessActivity.run(process.getIndividualProgramProcess(), AddGuidingsInformation.class, Collections.singletonList(bean)); addSuccessMessage(request, "message.guiding.created.with.success"); } catch (final DomainException e) { addErrorMessage(request, e.getKey(), e.getArgs()); return addGuidingInvalid(mapping, form, request, response); } RenderUtils.invalidateViewState(); return prepareEditCandidacyGuidings(mapping, form, request, response); } public ActionForward addGuidingInvalid(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); request.setAttribute("candidacyBean", getCandidacyBean()); request.setAttribute("guidingBean", getGuidingBean()); request.setAttribute("assistantGuidingBean", getAssistantGuidingBean()); canEditCandidacy(request, process.getCandidacyHashCode()); return mapping.findForward("editGuidings"); } public ActionForward addAssistantGuiding(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); PhdParticipantBean bean = getAssistantGuidingBean(); try { ExecuteProcessActivity.run(process.getIndividualProgramProcess(), AddAssistantGuidingInformation.class, bean); addSuccessMessage(request, "message.assistant.guiding.created.with.success"); } catch (final DomainException e) { addErrorMessage(request, e.getKey(), e.getArgs()); return addGuidingInvalid(mapping, form, request, response); } RenderUtils.invalidateViewState(); return prepareEditCandidacyGuidings(mapping, form, request, response); } public ActionForward removeGuiding(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); try { ExecuteProcessActivity.run(process.getIndividualProgramProcess(), DeleteGuiding.class, getDomainObject(request, "guidingId")); addSuccessMessage(request, "message.guiding.deleted.with.success"); } catch (final DomainException e) { addErrorMessage(request, e.getKey(), e.getArgs()); } return prepareEditCandidacyGuidings(mapping, form, request, response); } public ActionForward removeAssistantGuiding(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); try { ExecuteProcessActivity.run(process.getIndividualProgramProcess(), DeleteAssistantGuiding.class, getDomainObject(request, "guidingId")); addSuccessMessage(request, "message.guiding.deleted.with.success"); } catch (final DomainException e) { addErrorMessage(request, e.getKey(), e.getArgs()); } return prepareEditCandidacyGuidings(mapping, form, request, response); } private boolean hasAnyRefereeLetterViewStateInvalid() { for (final IViewState viewState : getViewStatesWithPrefixId("createRefereeLetterBean.")) { if (!viewState.isValid()) { return true; } } return false; } /* * Validate application */ public ActionForward prepareValidateApplication(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); final PhdProgramCandidacyProcessBean bean = new PhdProgramCandidacyProcessBean(process); canEditCandidacy(request, process.getCandidacyHashCode()); validateProcess(request, process.getIndividualProgramProcess()); request.setAttribute("candidacyBean", bean); return mapping.findForward("validateApplication"); } public ActionForward validateApplication(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); if (!validateProcess(request, process.getIndividualProgramProcess())) { return prepareValidateApplication(mapping, form, request, response); } try { ExecuteProcessActivity.run(process.getIndividualProgramProcess(), ValidatedByCandidate.class, null); addSuccessMessage(request, "message.validation.with.success"); } catch (final DomainException e) { addErrorMessage(request, e.getKey(), e.getArgs()); return prepareValidateApplication(mapping, form, request, response); } return viewCandidacy(mapping, form, request, response, process.getCandidacyHashCode()); } /* * * Upload photo */ public ActionForward prepareUploadPhoto(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { final PhdProgramCandidacyProcess process = getProcess(request); final PhdProgramCandidacyProcessBean bean = new PhdProgramCandidacyProcessBean(process); request.setAttribute("candidacyBean", bean); request.setAttribute("uploadPhotoBean", new PhotographUploadBean()); return mapping.findForward("uploadPhoto"); } public ActionForward uploadPhotoInvalid(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) { request.setAttribute("candidacyBean", getCandidacyBean()); request.setAttribute("uploadPhotoBean", getRenderedObject("uploadPhotoBean")); RenderUtils.invalidateViewState("uploadPhotoBean"); return mapping.findForward("uploadPhoto"); } public ActionForward uploadPhoto(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws IOException { final PhdProgramCandidacyProcessBean bean = getCandidacyBean(); final PhotographUploadBean photo = getRenderedObject("uploadPhotoBean"); if (!RenderUtils.getViewState("uploadPhotoBean").isValid()) { addErrorMessage(request, "error.photo.upload.invalid.information"); return uploadPhotoInvalid(mapping, actionForm, request, response); } if (ContentType.getContentType(photo.getContentType()) == null) { addErrorMessage(request, "error.photo.upload.unsupported.file"); return uploadPhotoInvalid(mapping, actionForm, request, response); } try { photo.processImage(); UploadOwnPhoto.upload(photo, bean.getIndividualProgramProcess().getPerson()); } catch (final UnableToProcessTheImage e) { addErrorMessage(request, "error.photo.upload.unable.to.process.image"); photo.deleteTemporaryFiles(); return uploadPhotoInvalid(mapping, actionForm, request, response); } catch (final DomainException e) { addErrorMessage(request, e.getKey(), e.getArgs()); photo.deleteTemporaryFiles(); return uploadPhotoInvalid(mapping, actionForm, request, response); } return viewCandidacy(mapping, actionForm, request, response, bean.getProcess().getCandidacyHashCode()); } private QualificationBean getQualificationBean() { return getRenderedObject("qualificationBean"); } private PhdIndividualProgramProcessBean getIndividualProcessBean() { return getRenderedObject("individualProcessBean"); } private PhdProgramDocumentUploadBean getUploadBean() { return getRenderedObject("documentByType"); } private PhdCandidacyRefereeBean getPhdCandidacyReferee() { return getRenderedObject("refereeBean"); } private PhdParticipantBean getGuidingBean() { return getRenderedObject("guidingBean"); } private PhdParticipantBean getAssistantGuidingBean() { return getRenderedObject("assistantGuidingBean"); } }