diff --git a/pom.xml b/pom.xml index 986f01300..d3c3c061a 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ eusurvey eusurvey war - 1.5.3 + 1.5.3.1 11 5.3.20 diff --git a/src/main/java/com/ec/survey/controller/RunnerController.java b/src/main/java/com/ec/survey/controller/RunnerController.java index 622ba064b..63075903d 100644 --- a/src/main/java/com/ec/survey/controller/RunnerController.java +++ b/src/main/java/com/ec/survey/controller/RunnerController.java @@ -1647,7 +1647,17 @@ public ModelAndView processDraftSubmit(@PathVariable String mode, HttpServletReq && user != null) { draft.getAnswerSet().setResponderEmail(user.getEmail()); } - + + //check that all readonly mandatory questions are answered + Question q = SurveyHelper.getFirstUnansweredMandatoryReadonlyQuestion(draft.getAnswerSet()); + if (q != null) { + String errorMessage = "Save as draft rejected as the draft contribution would be missing a value for this mandatory read-only question: " + q.getUniqueId(); + logger.error(errorMessage); + ModelAndView model = new ModelAndView(Constants.VIEW_ERROR_GENERIC); + model.addObject(Constants.MESSAGE, errorMessage); + return model; + } + try { answerService.saveDraft(draft, true); uid = draft.getUniqueId(); diff --git a/src/main/java/com/ec/survey/controller/WebServiceController.java b/src/main/java/com/ec/survey/controller/WebServiceController.java index 329a651e5..2ff0a3d4f 100644 --- a/src/main/java/com/ec/survey/controller/WebServiceController.java +++ b/src/main/java/com/ec/survey/controller/WebServiceController.java @@ -11,6 +11,7 @@ import com.ec.survey.tools.Constants; import com.ec.survey.tools.ConversionTools; import com.ec.survey.tools.MissingAnswersForReadonlyMandatoryQuestionException; +import com.ec.survey.tools.SurveyHelper; import com.ec.survey.tools.Tools; import com.ec.survey.tools.Ucs2Utf8; import com.ec.survey.tools.export.XmlExportCreator; @@ -1330,6 +1331,14 @@ private Survey getSurvey(String alias, User user, HttpServletRequest request, Ht response.setStatus(412); return ""; } + + //check that all readonly mandatory questions are answered + Question q = SurveyHelper.getFirstUnansweredMandatoryReadonlyQuestion(draft.getAnswerSet()); + if (q != null) { + logger.error("prefill call rejected as the draft contribution would be missing a value for this mandatory read-only question: " + q.getUniqueId()); + response.setStatus(412); + return ""; + } try { answerService.saveDraft(draft, true); diff --git a/src/main/java/com/ec/survey/tools/SurveyHelper.java b/src/main/java/com/ec/survey/tools/SurveyHelper.java index 7e12a6c5c..f4b29ff78 100644 --- a/src/main/java/com/ec/survey/tools/SurveyHelper.java +++ b/src/main/java/com/ec/survey/tools/SurveyHelper.java @@ -788,6 +788,31 @@ public static boolean validateElement(Element element, AnswerSet answerSet, return false; } } + + public static Question getFirstUnansweredMandatoryReadonlyQuestion(AnswerSet answerSet) { + //check that all readonly mandatory questions are answered + for (Question question : answerSet.getSurvey().getQuestions()) { + if (question instanceof MatrixOrTable && question.getReadonly()) { + MatrixOrTable m = (MatrixOrTable) question; + for (Element sub : m.getQuestions()) { + if (sub instanceof Text) { + Text t = (Text)sub; + if (!t.getOptional()) { + if (answerSet.getAnswers(t.getUniqueId()).isEmpty()) { + return t; + } + } + } + } + } else if (!question.getOptional() && question.getReadonly()) { + if (answerSet.getAnswers(question.getUniqueId()).isEmpty()) { + return question; + } + } + } + + return null; + } public static boolean checkDependencies(List questiondependencies, Element element, Question question, Matrix parent, AnswerSet answerSet, Set invisibleElements) { boolean found = false; diff --git a/src/main/java/com/ec/survey/tools/export/XmlExportCreator.java b/src/main/java/com/ec/survey/tools/export/XmlExportCreator.java index 78a0b2333..6b20f835a 100644 --- a/src/main/java/com/ec/survey/tools/export/XmlExportCreator.java +++ b/src/main/java/com/ec/survey/tools/export/XmlExportCreator.java @@ -9,8 +9,10 @@ import com.ec.survey.model.survey.*; import com.ec.survey.model.survey.ComplexTableItem.CellType; import com.ec.survey.model.survey.base.File; +import com.ec.survey.model.survey.quiz.QuizResult; import com.ec.survey.tools.Constants; import com.ec.survey.tools.ConversionTools; +import com.ec.survey.tools.QuizHelper; import com.ec.survey.tools.Tools; import org.apache.commons.compress.archivers.ArchiveOutputStream; import org.apache.commons.compress.archivers.ArchiveStreamFactory; @@ -420,13 +422,7 @@ public void exportContent(boolean sync, Export export, boolean fromWebService) t FilesByType explanationFilesToExport = new FilesByType<>(); HashMap values = new HashMap<>(); - - Map ECASUserLoginsByEmail = null; - - if (export.getAddMeta()) { - ECASUserLoginsByEmail = administrationService.getECASUserLoginsByEmail(); - } - + ResultFilter origFilter = answerService.initialize(export.getResultFilter()); ResultFilter filterWithMeta = export == null ? null : origFilter.copy(); @@ -461,13 +457,20 @@ public void exportContent(boolean sync, Export export, boolean fromWebService) t } filterWithMeta.setExportedQuestions(filterWithMeta.getVisibleQuestions()); - - List> answersets = reportingService.getAnswerSets(form.getSurvey(), filterWithMeta, null, false, + + // for quiz surveys we need the original answerSet instances in order to compute the scores + List> answersets = form.getSurvey().getIsQuiz() ? null : reportingService.getAnswerSets(form.getSurvey(), filterWithMeta, null, false, true, true, true, true, false); Map> uploadedFilesByQuestionUID = new HashMap<>(); writer.writeStartElement("Answers"); + + Map ECASUserLoginsByEmail = null; + + if (export.getAddMeta() || filterWithMeta.exported("user")) { + ECASUserLoginsByEmail = administrationService.getECASUserLoginsByEmail(); + } if (answersets != null) { @@ -770,17 +773,25 @@ void parseAnswerSet(Survey survey, XMLStreamWriter writer, List questio if (meta || filter == null || filter.exported("languages")) writer.writeAttribute("lang", answerSet == null ? row.get(rowPosMap.get("languages")) : answerSet.getLanguageCode()); - if (meta || filter == null || filter.exported("user")) - writer.writeAttribute("user", answerSet == null ? row.get(rowPosMap.get("user")) - : answerSet.getResponderEmail() != null ? answerSet.getResponderEmail() : ""); + if (meta || filter == null || filter.exported("user")) + if (survey.getSecurity().contains("anonymous")) { + writer.writeAttribute("user", "Anonymous"); + } else { + writer.writeAttribute("user", answerSet == null ? row.get(rowPosMap.get("user")): answerSet.getResponderEmail() != null ? answerSet.getResponderEmail() : ""); + } + if (meta || filter == null || filter.exported("invitation")) writer.writeAttribute("invitation", answerSet == null ? row.get(rowPosMap.get("invitation")) : answerSet.getInvitationId() != null ? answerSet.getInvitationId() : ""); - if (survey.getIsOPC() && (meta || filter == null || filter.exported("user"))) { - String suser = answerSet == null ? row.get(rowPosMap.get("user")) : answerSet.getResponderEmail(); - if (suser != null && suser.contains("@") && ECASUserLoginsByEmail != null - && ECASUserLoginsByEmail.containsKey(suser)) { - writer.writeAttribute("userlogin", ECASUserLoginsByEmail.get(suser)); + if (meta || filter == null || filter.exported("user")) { + if (survey.getSecurity().contains("anonymous")) { + writer.writeAttribute("userlogin", "Anonymous"); + } else { + String suser = answerSet == null ? row.get(rowPosMap.get("user")) : answerSet.getResponderEmail(); + if (suser != null && suser.contains("@") && ECASUserLoginsByEmail != null + && ECASUserLoginsByEmail.containsKey(suser)) { + writer.writeAttribute("userlogin", ECASUserLoginsByEmail.get(suser)); + } } } @@ -1160,6 +1171,36 @@ void parseAnswerSet(Survey survey, XMLStreamWriter writer, List questio } } } + + if (survey.getIsQuiz()) { + QuizResult quizResult = QuizHelper.getQuizResult(answerSet, survey); + writer.writeStartElement("Scores"); + + if (survey.getScoresByQuestion()) { + for (Element element : survey.getQuestionsAndSections()) { + if (element instanceof Section) { + String score = quizResult.getSectionScore(element.getUniqueId()); + if (!score.equals("0/0")) { + writer.writeStartElement("Section"); + writer.writeAttribute("id", element.getUniqueId()); + writer.writeCharacters(score); + writer.writeEndElement(); // Section + } + } else if (element instanceof ChoiceQuestion || element instanceof FreeTextQuestion || element instanceof NumberQuestion || element instanceof DateQuestion) { + Question question = (Question) element; + if (question.getScoring() > 0) { + writer.writeStartElement("Question"); + writer.writeAttribute("id", element.getUniqueId()); + writer.writeCharacters(quizResult.getQuestionScore(element.getUniqueId()) + "/" + quizResult.getQuestionMaximumScore(element.getUniqueId())); + writer.writeEndElement(); // Question + } + } + } + } + + writer.writeEndElement(); // Score + } + writer.writeEndElement(); // AnswerSet } diff --git a/src/main/webapp/WEB-INF/views/runner/runnercontentinner.jsp b/src/main/webapp/WEB-INF/views/runner/runnercontentinner.jsp index 38d0463e6..5ae2cf2b8 100644 --- a/src/main/webapp/WEB-INF/views/runner/runnercontentinner.jsp +++ b/src/main/webapp/WEB-INF/views/runner/runnercontentinner.jsp @@ -319,7 +319,7 @@ style="margin-top: 5px; display: none;"> -