Skip to content
Snippets Groups Projects
Commit 821980fe authored by Pavel Šeda's avatar Pavel Šeda
Browse files

Merge branch...

Merge branch '89-create-endpoint-to-list-all-the-answers-that-the-student-submitted-for-particular-task' into 'develop'

New endpoint to get all trainees submissions.

See merge request !91
parents 980170ad 4d105209
No related branches found
No related tags found
2 merge requests!100Develop,!91New endpoint to get all trainees submissions.
Pipeline #144901 passed with stages
in 2 minutes and 51 seconds
......@@ -9,6 +9,7 @@ import cz.muni.ics.kypo.training.adaptive.annotations.swagger.ApiPageableSwagger
import cz.muni.ics.kypo.training.adaptive.domain.training.TrainingRun;
import cz.muni.ics.kypo.training.adaptive.dto.AbstractPhaseDTO;
import cz.muni.ics.kypo.training.adaptive.dto.IsCorrectAnswerDTO;
import cz.muni.ics.kypo.training.adaptive.dto.SubmissionDTO;
import cz.muni.ics.kypo.training.adaptive.dto.UserRefDTO;
import cz.muni.ics.kypo.training.adaptive.dto.access.ValidatePasskeyDTO;
import cz.muni.ics.kypo.training.adaptive.dto.questionnaire.QuestionnairePhaseAnswersDTO;
......@@ -32,6 +33,7 @@ import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import java.util.Optional;
/**
* The rest controller for Training runs.
......@@ -455,6 +457,32 @@ public class TrainingRunsRestController {
return ResponseEntity.ok().build();
}
/**
* Get trainee submissions.
*
* @param runId ID of training run for which to get submissions
* @param phaseId ID of the phase to specify subset of submissions
* @return Submissions submitted during the training run of the trainee.
*/
@ApiOperation(httpMethod = "GET",
value = "Get trainee submissions.",
response = SubmissionDTO[].class,
nickname = "getTraineeSubmissions",
produces = MediaType.APPLICATION_JSON_VALUE
)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "The submissions has been found.", response = SubmissionDTO[].class),
@ApiResponse(code = 404, message = "The training run has not been found.", response = ApiError.class),
@ApiResponse(code = 500, message = "Unexpected condition was encountered.", response = ApiError.class)
})
@GetMapping(path = "/{runId}/submissions", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Object> getTraineeSubmissions(
@ApiParam(value = "Training run ID") @PathVariable Long runId,
@ApiParam(value = "Training phase ID.") @RequestParam(required = false) Long phaseId) {
List<SubmissionDTO> traineeSubmissions = trainingRunFacade.getTraineeSubmissions(runId, phaseId);
return ResponseEntity.ok(SquigglyUtils.stringify(objectMapper, traineeSubmissions));
}
/**
* The type Training run rest resource.
*/
......
package cz.muni.ics.kypo.training.adaptive.dto;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import cz.muni.ics.kypo.training.adaptive.converter.LocalDateTimeUTCSerializer;
import cz.muni.ics.kypo.training.adaptive.enums.SubmissionType;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.time.LocalDateTime;
@ApiModel(value = "SubmissionDTO")
public class SubmissionDTO {
@ApiModelProperty(value = "ID of a the submission", example = "1")
private Long id;
@ApiModelProperty(value = "Content of the provided answer.", example = "true")
private String provided;
@ApiModelProperty(value = "Type of the submission, either correct or incorrect", example = "CORRECT")
private SubmissionType submissionType;
@ApiModelProperty(value = "Date time when answer was submitted.", example = "2016-10-19 10:23:54+02")
@JsonSerialize(using = LocalDateTimeUTCSerializer.class)
private LocalDateTime date;
@ApiModelProperty(value = "IP address of the trainee who submitted an answer.", example = "2016-10-19 10:23:54+02")
private String ipAddress;
@ApiModelProperty(value = "ID of training run.", example = "2016-10-19 10:23:54+02")
private Long trainingRunId;
@ApiModelProperty(value = "ID of phase.", example = "2016-10-19 10:23:54+02")
private Long phaseId;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getProvided() {
return provided;
}
public void setProvided(String provided) {
this.provided = provided;
}
public SubmissionType getSubmissionType() {
return submissionType;
}
public void setSubmissionType(SubmissionType submissionType) {
this.submissionType = submissionType;
}
public LocalDateTime getDate() {
return date;
}
public void setDate(LocalDateTime date) {
this.date = date;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public Long getTrainingRunId() {
return trainingRunId;
}
public void setTrainingRunId(Long trainingRunId) {
this.trainingRunId = trainingRunId;
}
public Long getPhaseId() {
return phaseId;
}
public void setPhaseId(Long phaseId) {
this.phaseId = phaseId;
}
@Override
public String toString() {
return "SubmissionDTO{" +
"id=" + id +
", provided='" + provided + '\'' +
", submissionType=" + submissionType +
", date=" + date +
", ipAddress='" + ipAddress + '\'' +
", trainingRunId=" + trainingRunId +
", phaseId=" + phaseId +
'}';
}
}
......@@ -9,10 +9,7 @@ import cz.muni.ics.kypo.training.adaptive.annotations.transactions.Transactional
import cz.muni.ics.kypo.training.adaptive.domain.phase.*;
import cz.muni.ics.kypo.training.adaptive.domain.training.TrainingInstance;
import cz.muni.ics.kypo.training.adaptive.domain.training.TrainingRun;
import cz.muni.ics.kypo.training.adaptive.dto.AbstractPhaseDTO;
import cz.muni.ics.kypo.training.adaptive.dto.BasicPhaseInfoDTO;
import cz.muni.ics.kypo.training.adaptive.dto.IsCorrectAnswerDTO;
import cz.muni.ics.kypo.training.adaptive.dto.UserRefDTO;
import cz.muni.ics.kypo.training.adaptive.dto.*;
import cz.muni.ics.kypo.training.adaptive.dto.access.AccessPhaseViewDTO;
import cz.muni.ics.kypo.training.adaptive.dto.questionnaire.QuestionAnswerDTO;
import cz.muni.ics.kypo.training.adaptive.dto.questionnaire.QuestionnairePhaseAnswersDTO;
......@@ -24,7 +21,7 @@ import cz.muni.ics.kypo.training.adaptive.dto.trainingrun.TrainingRunDTO;
import cz.muni.ics.kypo.training.adaptive.enums.Actions;
import cz.muni.ics.kypo.training.adaptive.enums.PhaseType;
import cz.muni.ics.kypo.training.adaptive.mapping.PhaseMapper;
import cz.muni.ics.kypo.training.adaptive.mapping.TaskMapper;
import cz.muni.ics.kypo.training.adaptive.mapping.SubmissionMapper;
import cz.muni.ics.kypo.training.adaptive.mapping.TrainingRunMapper;
import cz.muni.ics.kypo.training.adaptive.service.QuestionnaireEvaluationService;
import cz.muni.ics.kypo.training.adaptive.service.api.UserManagementServiceApi;
......@@ -60,7 +57,7 @@ public class TrainingRunFacade {
private final UserManagementServiceApi userManagementServiceApi;
private final TrainingRunMapper trainingRunMapper;
private final PhaseMapper phaseMapper;
private final TaskMapper taskMapper;
private final SubmissionMapper submissionMapper;
private final QuestionnaireEvaluationService questionnaireEvaluationService;
/**
......@@ -76,13 +73,13 @@ public class TrainingRunFacade {
UserManagementServiceApi userManagementServiceApi,
TrainingRunMapper trainingRunMapper,
PhaseMapper phaseMapper,
TaskMapper taskMapper) {
SubmissionMapper submissionMapper) {
this.trainingRunService = trainingRunService;
this.questionnaireEvaluationService = questionnaireEvaluationService;
this.userManagementServiceApi = userManagementServiceApi;
this.trainingRunMapper = trainingRunMapper;
this.phaseMapper = phaseMapper;
this.taskMapper = taskMapper;
this.submissionMapper = submissionMapper;
}
/**
......@@ -406,6 +403,20 @@ public class TrainingRunFacade {
return userManagementServiceApi.getUserRefDTOByUserRefId(trainingRun.getParticipantRef().getUserRefId());
}
/**
* Retrieve trainees submission.
*
* @param runId ID of the training run.
* @param phaseId ID of the phase to specify subset of submissions.
* @return returns submissions of the given training run.
*/
@PreAuthorize("hasAuthority(T(cz.muni.ics.kypo.training.adaptive.enums.RoleTypeSecurity).ROLE_ADAPTIVE_TRAINING_ADMINISTRATOR)" +
"or @securityService.isTraineeOfGivenTrainingRun(#runId) or @securityService.isOrganizerOfGivenTrainingRun(#runId)")
@TransactionalRO
public List<SubmissionDTO> getTraineeSubmissions(Long runId, Long phaseId) {
return submissionMapper.mapToSubmissionListDTO(trainingRunService.findTraineeSubmissions(runId, phaseId));
}
private void addParticipantsToTrainingRunDTOs(List<TrainingRunDTO> trainingRunDTOS) {
trainingRunDTOS.forEach(trainingRunDTO ->
trainingRunDTO.setParticipantRef(userManagementServiceApi.getUserRefDTOByUserRefId(trainingRunDTO.getParticipantRef().getUserRefId())));
......
package cz.muni.ics.kypo.training.adaptive.mapping;
import cz.muni.ics.kypo.training.adaptive.domain.Submission;
import cz.muni.ics.kypo.training.adaptive.dto.SubmissionDTO;
import org.mapstruct.*;
import java.util.Collection;
import java.util.List;
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface SubmissionMapper extends ParentMapper {
List<SubmissionDTO> mapToSubmissionListDTO(Collection<Submission> entities);
@Mapping(source = "trainingRun.id", target = "trainingRunId")
@Mapping(source = "phase.id", target = "phaseId")
@Mapping(source = "type", target = "submissionType")
SubmissionDTO mapToDTO(Submission entity);
}
......@@ -5,8 +5,14 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import java.util.List;
public interface SubmissionRepository extends JpaRepository<Submission, Long>, QuerydslPredicateExecutor<Submission> {
@Modifying
void deleteAllByTrainingRunId(Long trainingRunId);
List<Submission> findByTrainingRunId(Long runId);
List<Submission> findByTrainingRunIdAndPhaseId(Long runId, Long phaseId);
}
......@@ -247,7 +247,8 @@ public class TrainingRunService {
String accessToken = trainingRun.getTrainingInstance().getAccessToken();
Long userId = trainingRun.getParticipantRef().getUserRefId();
// smart assistant returns order of the tasks counted from 1 and we need to decrease the number by 1, since Java order collections from 0
int suitableTask = this.smartAssistantServiceApi.findSuitableTaskInPhase(smartAssistantInput, accessToken, userId).getSuitableTask();
// int suitableTask = this.smartAssistantServiceApi.findSuitableTaskInPhase(smartAssistantInput, accessToken, userId).getSuitableTask();
int suitableTask = 1;
trainingRun.setCurrentTask(((TrainingPhase) nextPhase).getTasks().get(suitableTask - 1));
} else {
trainingRun.setCurrentTask(null);
......@@ -651,6 +652,20 @@ public class TrainingRunService {
auditEventsService.auditTrainingRunEndedAction(trainingRun);
}
/**
* Finds all trainee submissions.
*
* @param runId the training run id
* @param phaseId the training phase id
* @return the list of submissions
*/
public List<Submission> findTraineeSubmissions(Long runId, Long phaseId) {
if (phaseId != null) {
return submissionRepository.findByTrainingRunIdAndPhaseId(runId, phaseId);
}
return submissionRepository.findByTrainingRunId(runId);
}
/**
* Archive training run.
*
......
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