Commit bc19954c authored by Kevin Robert's avatar Kevin Robert
Browse files

UNOTOPLYS-319 : Modification de l'export pour afficher les libellés des questions et des réponses.

parent 4d812f17
package com.unantes.orientactive.converter.bean;
import com.unantes.orientactive.export.ExportableItem;
import com.unantes.orientactive.web.api.model.ChoiceAPI;
import com.unantes.orientactive.web.api.model.MultipleChoiceItemAPI;
import org.apache.commons.lang3.StringUtils;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
/**
* Représentation d'un élément à choix multiples.
*/
public class MultipleChoiceItem extends AbstractQuestion {
public class MultipleChoiceItem extends AbstractQuestion implements ExportableItem {
/**
* La question.
......@@ -63,6 +65,28 @@ public class MultipleChoiceItem extends AbstractQuestion {
}
}
@Override
public List<String> getExportAnswersLabels(List<String> answers) {
return answers.stream().map(this::getLabelForValue).collect(Collectors.toList());
}
private String getLabelForValue(String code) {
return choices.stream().filter(choice -> choice.getValue().equals(code)).findFirst().orElseThrow().getLabel();
}
@Override
public String getExportQuestionLabel() {
if (StringUtils.isBlank(shortLabel)) {
return this.question;
}
return shortLabel;
}
@Override
public String getExportQuestionReference() {
return reference;
}
public List<Choice> getChoices() {
return choices;
}
......
package com.unantes.orientactive.converter.bean;
import com.unantes.orientactive.export.ExportableItem;
import com.unantes.orientactive.web.api.model.OpenQuestionItemAPI;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
/**
* Représentation d'une question ouverte.
*/
public class OpenQuestion extends Item {
public class OpenQuestion extends Item implements ExportableItem {
/**
* La question ouverte.
......@@ -40,6 +43,25 @@ public class OpenQuestion extends Item {
return openQuestionItemAPI;
}
@Override
public List<String> getExportAnswersLabels(List<String> answers) {
// On n'a pas de code, la réponse est directement la valeur à exporter.
return answers;
}
@Override
public String getExportQuestionLabel() {
if (StringUtils.isBlank(shortLabel)) {
return this.question;
}
return shortLabel;
}
@Override
public String getExportQuestionReference() {
return reference;
}
public String getQuestion() {
return question;
}
......
......@@ -3,8 +3,10 @@ package com.unantes.orientactive.export;
import com.unantes.orientactive.converter.bean.AnswerElements;
import com.unantes.orientactive.service.AnswerService;
import com.unantes.orientactive.service.FormService;
import com.unantes.orientactive.service.ScreenService;
import com.unantes.orientactive.service.dto.AnswerDTO;
import com.unantes.orientactive.service.dto.FormDTO;
import com.unantes.orientactive.service.dto.ScreenDTO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
......@@ -15,6 +17,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
......@@ -39,15 +42,22 @@ public class ExportService {
*/
private AnswerService answerService;
/**
* Service des écrans.
*/
private ScreenService screenService;
/**
* Constructeur complet.
*
* @param formService Le service des formulaires.
* @param answerService Le service des réponses.
* @param screenService Le service des écrans.
*/
public ExportService(final FormService formService, final AnswerService answerService) {
public ExportService(final FormService formService, final AnswerService answerService, final ScreenService screenService) {
this.formService = formService;
this.answerService = answerService;
this.screenService = screenService;
}
/**
......@@ -68,9 +78,12 @@ public class ExportService {
final FormDTO formDTO = formOptional.get();
final List<String> questions = formService.getAllQuestionReferenceForForm(formDTO.getId());
final List<String> sessions = formService.getAllRepondingUserForForm(formDTO.getId());
final List<ScreenDTO> screens = screenService.findAllByFormId(formDTO.getId());
final Map<String, String> questionsLabels = findQuestionsLabels(screens);
// @formatter:off
String[] header = {"SessionId"};
String[] headerAnswers = questions.toArray(new String[sessions.size()]);
String[] headerAnswers = questions.stream().map(questionsLabels::get).toArray(String[]::new);
String[] completeHeader = ArrayUtils.addAll(header, headerAnswers);
final CSVPrinter csvPrinter = CSVFormat.EXCEL
.withDelimiter(columnsDelimeter)
......@@ -80,17 +93,32 @@ public class ExportService {
for (int i = 0; i < sessions.size(); i++) {
batchSessions.add(sessions.get(i));
if (i % 100 == 0) {
writeToCsv(answersDelimiter, formDTO, questions, csvPrinter, batchSessions);
writeToCsv(answersDelimiter, formDTO, questions, csvPrinter, batchSessions, screens);
batchSessions = new LinkedList<>();
}
}
writeToCsv(answersDelimiter, formDTO, questions, csvPrinter, batchSessions);
writeToCsv(answersDelimiter, formDTO, questions, csvPrinter, batchSessions, screens);
csvPrinter.flush();
}
private void writeToCsv(String answersDelimiter, FormDTO formDTO, List<String> questions, CSVPrinter csvPrinter, List<String> batchSessions) throws IOException {
final List<ISessionAnswers> sessionsAnswers = getSessionsAnswers(formDTO, batchSessions);
for (ISessionAnswers sessionAnswer: sessionsAnswers) {
/**
* Récupération des labels des questions.
*
* @param screens Les écrans.
* @return Les labels.
*/
private Map<String, String> findQuestionsLabels(List<ScreenDTO> screens) {
final Map<String, String> questionsLabels = new HashMap<>();
screens.stream().map(ScreenDTO::getItemsList).flatMap(List::stream)
.filter(item -> item instanceof ExportableItem)
.map(item -> (ExportableItem) item)
.forEach(exportableItem -> questionsLabels.put(exportableItem.getExportQuestionReference(), exportableItem.getExportQuestionLabel()));
return questionsLabels;
}
private void writeToCsv(String answersDelimiter, FormDTO formDTO, List<String> questions, CSVPrinter csvPrinter, List<String> batchSessions, List<ScreenDTO> screens) throws IOException {
final List<ISessionAnswers> sessionsAnswers = getSessionsAnswers(formDTO, batchSessions, screens);
for (ISessionAnswers sessionAnswer : sessionsAnswers) {
final List<String> csvLines = sessionAnswer.generateCsv(questions, answersDelimiter);
csvPrinter.printRecord(csvLines);
}
......@@ -99,11 +127,11 @@ public class ExportService {
/**
* Récupération des réponses pour une session.
*
* @param formDTO Le formulaires.
* @param formDTO Le formulaires.
* @param sessions L'identifiant de session de l'utilisateur.
* @return Les réponses des formulaires.
*/
private List<ISessionAnswers> getSessionsAnswers(final FormDTO formDTO, final List<String> sessions) {
private List<ISessionAnswers> getSessionsAnswers(final FormDTO formDTO, final List<String> sessions, final List<ScreenDTO> screens) {
final List<ISessionAnswers> answers = new LinkedList<>();
final List<AnswerDTO> answerDTOS = answerService.getSessionAnswers(sessions, formDTO.getId());
for (final String session : sessions) {
......@@ -117,9 +145,8 @@ public class ExportService {
.filter(answerElement -> CollectionUtils.isNotEmpty(answerElement.getAnswer()))
.collect(Collectors.toMap(AnswerElements::getQuestionReference, Function.identity()));
// @formatter:on
answers.add(new SessionAnswers(session, answersElements));
answers.add(new SessionAnswers(session, answersElements, screens));
}
return answers;
}
}
package com.unantes.orientactive.export;
import java.util.List;
/**
* Interface des éléments présents dans l'export.
*/
public interface ExportableItem {
/**
* Le libellé de la question.
*
* @return Le libellé.
*/
String getExportQuestionLabel();
/**
* La réfrence de la question.
*
* @return La référence.
*/
String getExportQuestionReference();
/**
* La liste des libellés de réponses.
*
* @param answers Les codes des réponses.
* @return Les réponses.
*/
List<String> getExportAnswersLabels(List<String> answers);
}
package com.unantes.orientactive.export;
import com.unantes.orientactive.converter.bean.AnswerElements;
import com.unantes.orientactive.converter.bean.Item;
import com.unantes.orientactive.service.dto.ScreenDTO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* Représentation des réponses d'un formulaire pour un utilisateur (une session).
......@@ -23,6 +26,11 @@ public class SessionAnswers implements ISessionAnswers {
*/
private Map<String, AnswerElements> answerElements;
/**
* La liste des écrans.
*/
private List<ScreenDTO> screens;
/**
* Constructeur vide.
*/
......@@ -35,11 +43,13 @@ public class SessionAnswers implements ISessionAnswers {
*
* @param sessionId L'identifiant de l'utilisateur.
* @param answerElements Les réponses.
* @param screens Les écrans.
*/
public SessionAnswers(String sessionId, Map<String, AnswerElements> answerElements) {
public SessionAnswers(String sessionId, Map<String, AnswerElements> answerElements, List<ScreenDTO> screens) {
super();
this.sessionId = sessionId;
this.answerElements = answerElements;
this.screens = screens;
}
/**
......@@ -47,7 +57,7 @@ public class SessionAnswers implements ISessionAnswers {
* Quand une réponse possède plusieurs éléments, ceux-ci sont séparés par une virgule.
*
* @param questionsReferences Les références des questions.
* @param answersDelimiter Charactère petmettant de délimiter les différentes réponses au sein d'une colonne dans l'export CSV.
* @param answersDelimiter Charactère petmettant de délimiter les différentes réponses au sein d'une colonne dans l'export CSV.
* @return Les lignes correspondantes aux réponses de l'utilisateur aux questions.
*/
@Override
......@@ -62,19 +72,29 @@ public class SessionAnswers implements ISessionAnswers {
/**
* Calcule la valeur d'une cellule de la ligne.
*
* @param questionReference la reference de la question de la colonne de la cellule
* @param answersDelimiter le séparateur de réponse en cas de réponses multiples
* @param answersDelimiter le séparateur de réponse en cas de réponses multiples
* @return
*/
public String getCellValue(final String questionReference, final String answersDelimiter) {
if (!answerElements.containsKey(questionReference)) {
return StringUtils.EMPTY;
}
final List<String> answer = answerElements.get(questionReference).getAnswer();
if (CollectionUtils.isEmpty(answer)) {
return StringUtils.EMPTY;
Optional<Item> questionOptional = screens.stream().map(ScreenDTO::getItemsList).flatMap(List::stream)
.filter(item -> item instanceof ExportableItem)
.filter(item -> item.getReference().equals(questionReference))
.findFirst();
if (questionOptional.isPresent()) {
ExportableItem exportableQuestion = (ExportableItem) questionOptional.get();
if (!answerElements.containsKey(questionReference)) {
return StringUtils.EMPTY;
}
final List<String> answers = answerElements.get(questionReference).getAnswer();
if (CollectionUtils.isEmpty(answers)) {
return StringUtils.EMPTY;
}
final List<String> answerLabel = exportableQuestion.getExportAnswersLabels(answers);
return String.join(answersDelimiter, answerLabel);
}
return String.join(answersDelimiter, answer);
return StringUtils.EMPTY;
}
public String getSessionId() {
......
package com.unantes.orientactive.service;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.hibernate.exception.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
......@@ -29,6 +15,19 @@ import com.unantes.orientactive.service.exception.EntityNotFoundException;
import com.unantes.orientactive.service.mapper.ScreenMapper;
import com.unantes.orientactive.service.mapper.ScreenPanelMapper;
import com.unantes.orientactive.web.rest.errors.ScreenAlreadyAnsweredException;
import org.hibernate.exception.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* Service Implementation for managing {@link Screen}.
......@@ -216,6 +215,16 @@ public class ScreenService {
return screenRepository.findAllByFormId(formId);
}
/**
* Récupération des écrans d'un formulaire sans passer par les droits.
*
* @param formId L'identifiant du formulaire.
* @return La liste des écrans.
*/
public List<ScreenDTO> findAllByFormId(Long formId) {
return screenRepository.findAllByFormId(formId).stream().map(screenMapper::toDto).collect(Collectors.toList());
}
/**
* Récupération de l'écran via son index et son formulaire.
*
......@@ -229,7 +238,8 @@ public class ScreenService {
/**
* Modifie les élements de l'écran ciblés par le patch. Si l'index est modifié : met à jour les écrans impactés.
* @param id un identifiant d'écran en base de donnée
*
* @param id un identifiant d'écran en base de donnée
* @param patch le patch à appliquer
* @return
*/
......@@ -249,7 +259,8 @@ public class ScreenService {
/**
* Met à jour si nécessaire l'ordre d'un écran et ceux des écrans impactés
* @param oldScreen l'ancien écran
*
* @param oldScreen l'ancien écran
* @param patchedScreen l'écran modifié
*/
public void updateScreenOrder(final ScreenDTO oldScreen, final ScreenDTO patchedScreen) {
......@@ -264,7 +275,8 @@ public class ScreenService {
/**
* Met à jour l'ordre d'un écran et ceux des écrans impactés
* @param id l'ancien écran
*
* @param id l'ancien écran
* @param oldIndex l'écran modifié
* @param newIndex l'écran modifié
*/
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment