Skip to content
Snippets Groups Projects
Commit 5b2559b6 authored by Jan Tymel's avatar Jan Tymel
Browse files

Fix some issues with questionnaire model

Related to #7, #3
parent b60b1403
No related branches found
No related tags found
No related merge requests found
...@@ -23,11 +23,14 @@ public class QuestionPhaseRelation { ...@@ -23,11 +23,14 @@ public class QuestionPhaseRelation {
private Integer order; private Integer order;
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)
private QuestionnairePhase relatedPhase; private QuestionnairePhase questionnairePhase;
@ManyToOne(fetch = FetchType.LAZY)
private TrainingPhase relatedPhase;
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinTable(name = "question_phase_relation_question", @JoinTable(name = "question_phase_relation_question",
joinColumns = @JoinColumn(name = "question_phase_id"), joinColumns = @JoinColumn(name = "question_phase_relation_id"),
inverseJoinColumns = @JoinColumn(name = "question_id") inverseJoinColumns = @JoinColumn(name = "question_id")
) )
private Set<Question> questions; private Set<Question> questions;
...@@ -50,11 +53,19 @@ public class QuestionPhaseRelation { ...@@ -50,11 +53,19 @@ public class QuestionPhaseRelation {
this.order = order; this.order = order;
} }
public QuestionnairePhase getRelatedPhase() { public QuestionnairePhase getQuestionnairePhase() {
return questionnairePhase;
}
public void setQuestionnairePhase(QuestionnairePhase questionnairePhase) {
this.questionnairePhase = questionnairePhase;
}
public TrainingPhase getRelatedPhase() {
return relatedPhase; return relatedPhase;
} }
public void setRelatedPhase(QuestionnairePhase relatedPhase) { public void setRelatedPhase(TrainingPhase relatedPhase) {
this.relatedPhase = relatedPhase; this.relatedPhase = relatedPhase;
} }
......
...@@ -23,7 +23,7 @@ public class QuestionnairePhase extends AbstractPhase { ...@@ -23,7 +23,7 @@ public class QuestionnairePhase extends AbstractPhase {
private List<Question> questions = new ArrayList<>(); private List<Question> questions = new ArrayList<>();
@OrderBy @OrderBy
@OneToMany(mappedBy = "relatedPhase", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) @OneToMany(mappedBy = "questionnairePhase", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private List<QuestionPhaseRelation> questionPhaseRelations = new ArrayList<>(); private List<QuestionPhaseRelation> questionPhaseRelations = new ArrayList<>();
public List<Question> getQuestions() { public List<Question> getQuestions() {
......
...@@ -20,7 +20,7 @@ public abstract class AbstractQuestionDto implements Serializable { ...@@ -20,7 +20,7 @@ public abstract class AbstractQuestionDto implements Serializable {
@ApiModelProperty(value = "It defines the type of the question", allowableValues = "FFQ, MCQ, RFQ", required = true, example = "MCQ") @ApiModelProperty(value = "It defines the type of the question", allowableValues = "FFQ, MCQ, RFQ", required = true, example = "MCQ")
@NotNull(message = "Question type must be specified") @NotNull(message = "Question type must be specified")
private QuestionType type; private QuestionType questionType;
@ApiModelProperty(value = "Choices that are distributed with the question", required = true) @ApiModelProperty(value = "Choices that are distributed with the question", required = true)
private List<QuestionChoiceDto> choices; private List<QuestionChoiceDto> choices;
...@@ -41,12 +41,12 @@ public abstract class AbstractQuestionDto implements Serializable { ...@@ -41,12 +41,12 @@ public abstract class AbstractQuestionDto implements Serializable {
this.text = text; this.text = text;
} }
public QuestionType getType() { public QuestionType getQuestionType() {
return type; return questionType;
} }
public void setType(QuestionType type) { public void setQuestionType(QuestionType type) {
this.type = type; this.questionType = type;
} }
public List<QuestionChoiceDto> getChoices() { public List<QuestionChoiceDto> getChoices() {
......
...@@ -2,7 +2,6 @@ package com.example.demo.dto; ...@@ -2,7 +2,6 @@ package com.example.demo.dto;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import javax.validation.Valid;
import javax.validation.constraints.Max; import javax.validation.constraints.Max;
import javax.validation.constraints.Min; import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
...@@ -17,9 +16,12 @@ public class QuestionPhaseRelationDto { ...@@ -17,9 +16,12 @@ public class QuestionPhaseRelationDto {
@NotNull(message = "Question order must be specified") @NotNull(message = "Question order must be specified")
private Integer order; private Integer order;
@Valid @ApiModelProperty(value = "Set of IDs of questions related to the specified questionnaire")
@ApiModelProperty(value = "Set of questions related to the specified questionnaire") private Set<Long> questionIds;
private Set<QuestionRequiredIdDto> questions;
@ApiModelProperty(value = "ID of training phase to which the questions are related of question", required = true, example = "1")
@NotNull(message = "Phase ID in question-phase relations must not be null")
private Long phaseId;
@ApiModelProperty(value = "Percentage that defines whether a player was successful or not ", required = true, example = "50") @ApiModelProperty(value = "Percentage that defines whether a player was successful or not ", required = true, example = "50")
@Min(value = 0, message = "Success rate must not be lower than 0 %") @Min(value = 0, message = "Success rate must not be lower than 0 %")
...@@ -42,12 +44,20 @@ public class QuestionPhaseRelationDto { ...@@ -42,12 +44,20 @@ public class QuestionPhaseRelationDto {
this.order = order; this.order = order;
} }
public Set<QuestionRequiredIdDto> getQuestions() { public Set<Long> getQuestionIds() {
return questions; return questionIds;
}
public void setQuestionIds(Set<Long> questionIds) {
this.questionIds = questionIds;
}
public Long getPhaseId() {
return phaseId;
} }
public void setQuestions(Set<QuestionRequiredIdDto> questions) { public void setPhaseId(Long phaseId) {
this.questions = questions; this.phaseId = phaseId;
} }
public int getSuccessRate() { public int getSuccessRate() {
......
package com.example.demo.repository;
import com.example.demo.domain.QuestionPhaseRelation;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface QuestionPhaseRelationRepository extends JpaRepository<QuestionPhaseRelation, Long> {
@Query("SELECT COALESCE(MAX(q.order), -1) FROM QuestionPhaseRelation q WHERE q.questionnairePhase.id = :phaseId")
Integer getCurrentMaxOrder(@Param("phaseId") Long phaseId);
}
package com.example.demo.service; package com.example.demo.service;
import com.example.demo.domain.Question; import com.example.demo.domain.Question;
import com.example.demo.domain.QuestionPhaseRelation;
import com.example.demo.domain.QuestionnairePhase; import com.example.demo.domain.QuestionnairePhase;
import com.example.demo.domain.TrainingPhase;
import com.example.demo.dto.PhaseCreateDTO; import com.example.demo.dto.PhaseCreateDTO;
import com.example.demo.dto.QuestionPhaseRelationDto;
import com.example.demo.dto.QuestionnairePhaseDto; import com.example.demo.dto.QuestionnairePhaseDto;
import com.example.demo.dto.QuestionnaireUpdateDto; import com.example.demo.dto.QuestionnaireUpdateDto;
import com.example.demo.enums.PhaseType; import com.example.demo.enums.PhaseType;
import com.example.demo.enums.QuestionnaireType; import com.example.demo.enums.QuestionnaireType;
import com.example.demo.mapper.BeanMapper; import com.example.demo.mapper.BeanMapper;
import com.example.demo.repository.AbstractPhaseRepository; import com.example.demo.repository.AbstractPhaseRepository;
import com.example.demo.repository.QuestionPhaseRelationRepository;
import com.example.demo.repository.QuestionRepository;
import com.example.demo.repository.QuestionnairePhaseRepository; import com.example.demo.repository.QuestionnairePhaseRepository;
import com.example.demo.repository.TrainingPhaseRepository;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.util.Optional; import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@Service @Service
public class QuestionnairePhaseService { public class QuestionnairePhaseService {
...@@ -29,9 +38,18 @@ public class QuestionnairePhaseService { ...@@ -29,9 +38,18 @@ public class QuestionnairePhaseService {
@Autowired @Autowired
private AbstractPhaseRepository abstractPhaseRepository; private AbstractPhaseRepository abstractPhaseRepository;
@Autowired
private QuestionRepository questionRepository;
@Autowired
private TrainingPhaseRepository trainingPhaseRepository;
@Autowired
private QuestionPhaseRelationRepository questionPhaseRelationRepository;
public QuestionnairePhaseDto createDefaultQuestionnairePhase(Long trainingDefinitionId, PhaseCreateDTO phaseCreateDTO) { public QuestionnairePhaseDto createDefaultQuestionnairePhase(Long trainingDefinitionId, PhaseCreateDTO phaseCreateDTO) {
QuestionnairePhase questionnairePhase =new QuestionnairePhase(); QuestionnairePhase questionnairePhase = new QuestionnairePhase();
questionnairePhase.setTitle("Title of questionnaire level"); questionnairePhase.setTitle("Title of questionnaire level");
questionnairePhase.setTrainingDefinitionId(trainingDefinitionId); questionnairePhase.setTrainingDefinitionId(trainingDefinitionId);
questionnairePhase.setOrder(abstractPhaseRepository.getCurrentMaxOrder(trainingDefinitionId) + 1); questionnairePhase.setOrder(abstractPhaseRepository.getCurrentMaxOrder(trainingDefinitionId) + 1);
...@@ -47,24 +65,6 @@ public class QuestionnairePhaseService { ...@@ -47,24 +65,6 @@ public class QuestionnairePhaseService {
return BeanMapper.INSTANCE.toDto(persistedEntity); return BeanMapper.INSTANCE.toDto(persistedEntity);
} }
public QuestionnairePhaseDto updateQuestion(QuestionnairePhase questionnairePhase) {
Optional<QuestionnairePhase> persistedQuestion = questionnairePhaseRepository.findById(questionnairePhase.getId());
if (persistedQuestion.isEmpty()) {
// TODO return 404
LOG.error("No questionnaire level found with ID {}.", questionnairePhase.getId());
return new QuestionnairePhaseDto();
}
questionnairePhase.setTrainingDefinitionId(persistedQuestion.get().getTrainingDefinitionId());
questionnairePhase.setQuestions(persistedQuestion.get().getQuestions());
questionnairePhase.setOrder(persistedQuestion.get().getOrder());
QuestionnairePhase savedEntity = questionnairePhaseRepository.save(questionnairePhase);
return BeanMapper.INSTANCE.toDto(savedEntity);
}
public QuestionnairePhaseDto updateQuestionnairePhase(Long definitionId, Long phaseId, QuestionnaireUpdateDto questionnaireUpdateDto) { public QuestionnairePhaseDto updateQuestionnairePhase(Long definitionId, Long phaseId, QuestionnaireUpdateDto questionnaireUpdateDto) {
QuestionnairePhase questionnairePhase = BeanMapper.INSTANCE.toEntity(questionnaireUpdateDto); QuestionnairePhase questionnairePhase = BeanMapper.INSTANCE.toEntity(questionnaireUpdateDto);
questionnairePhase.setId(phaseId); questionnairePhase.setId(phaseId);
...@@ -75,13 +75,11 @@ public class QuestionnairePhaseService { ...@@ -75,13 +75,11 @@ public class QuestionnairePhaseService {
// TODO add check to trainingDefinitionId and phaseId (field structure will be probably changed); // TODO add check to trainingDefinitionId and phaseId (field structure will be probably changed);
questionnairePhase.setTrainingDefinitionId(persistedQuestionnairePhase.getTrainingDefinitionId()); questionnairePhase.setTrainingDefinitionId(persistedQuestionnairePhase.getTrainingDefinitionId());
questionnairePhase.setOrder(persistedQuestionnairePhase.getOrder()); questionnairePhase.setOrder(persistedQuestionnairePhase.getOrder());
if (!CollectionUtils.isEmpty(questionnairePhase.getQuestionPhaseRelations())) { questionnairePhase.getQuestionPhaseRelations().clear();
questionnairePhase.getQuestionPhaseRelations().forEach(x -> x.setRelatedPhase(questionnairePhase)); questionnairePhase.getQuestionPhaseRelations().addAll(resolveQuestionnairePhaseRelationsUpdate(questionnairePhase, questionnaireUpdateDto));
}
if (!CollectionUtils.isEmpty(questionnairePhase.getQuestions())) { if (!CollectionUtils.isEmpty(questionnairePhase.getQuestions())) {
questionnairePhase.getQuestions().forEach(x -> x.setQuestionnairePhase(questionnairePhase)); questionnairePhase.getQuestions().forEach(x -> x.setQuestionnairePhase(questionnairePhase));
...@@ -92,6 +90,52 @@ public class QuestionnairePhaseService { ...@@ -92,6 +90,52 @@ public class QuestionnairePhaseService {
QuestionnairePhase savedEntity = questionnairePhaseRepository.save(questionnairePhase); QuestionnairePhase savedEntity = questionnairePhaseRepository.save(questionnairePhase);
return BeanMapper.INSTANCE.toDto(savedEntity); QuestionnairePhaseDto result = BeanMapper.INSTANCE.toDto(savedEntity);
if (QuestionnaireType.ADAPTIVE.equals(savedEntity.getQuestionnaireType())) {
result.setPhaseType(PhaseType.QUESTIONNAIRE_ADAPTIVE);
} else {
result.setPhaseType(PhaseType.QUESTIONNAIRE_GENERAL);
}
return result;
} }
private List<QuestionPhaseRelation> resolveQuestionnairePhaseRelationsUpdate(QuestionnairePhase questionnairePhase, QuestionnaireUpdateDto questionnaireUpdateDto) {
List<QuestionPhaseRelation> questionnairePhaseRelations = new ArrayList<>();
if (!CollectionUtils.isEmpty(questionnaireUpdateDto.getPhaseRelations())) {
int order = 0;
for (QuestionPhaseRelationDto phaseRelation : questionnaireUpdateDto.getPhaseRelations()) {
Set<Question> questionsInPhaseRelation = Set.copyOf(questionRepository.findAllById(phaseRelation.getQuestionIds()));
QuestionPhaseRelation questionPhaseRelation;
if (Objects.isNull(phaseRelation.getId())) {
questionPhaseRelation = new QuestionPhaseRelation();
questionPhaseRelation.setQuestions(questionsInPhaseRelation);
} else {
questionPhaseRelation = questionPhaseRelationRepository.findById(phaseRelation.getId())
.orElseThrow(() -> new RuntimeException("Question phase relation was not found"));
// TODO throw proper exception once kypo2-training is migrated
questionPhaseRelation.getQuestions().clear();
questionPhaseRelation.getQuestions().addAll(questionsInPhaseRelation);
}
TrainingPhase trainingPhase = trainingPhaseRepository.findById(phaseRelation.getPhaseId())
.orElseThrow(() -> new RuntimeException("Training phase was not found"));
// TODO throw proper exception once kypo2-training is migrated
questionPhaseRelation.setOrder(order);
questionPhaseRelation.setSuccessRate(phaseRelation.getSuccessRate());
questionPhaseRelation.setRelatedPhase(trainingPhase);
questionPhaseRelation.setQuestionnairePhase(questionnairePhase);
questionnairePhaseRelations.add(questionPhaseRelation);
order++;
}
}
return questionnairePhaseRelations;
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment