diff --git a/.gitignore b/.gitignore
index 491f10dd9d91e03c7187da85178b3b3358c4b1a9..9e9fe03aa6f08e57eb86f9d6ca1c0f985a431ce1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,6 +19,9 @@ target/
 *.iml
 *.ipr
 
+### Spring ###
+*.log*
+
 ### NetBeans ###
 /nbproject/private/
 /nbbuild/
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/PhasesController.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/PhasesController.java
index ab9fe85604f607d55d751559e5e7644f8a55e857..86d3547994b952b9d4d72c52f076b13972adcf9c 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/PhasesController.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/PhasesController.java
@@ -21,8 +21,6 @@ import java.util.List;
 
 @RestController
 @RequestMapping(value = "/training-definitions/{definitionId}/phases", produces = MediaType.APPLICATION_JSON_VALUE)
-@CrossOrigin(origins = "*", allowCredentials = "true", allowedHeaders = "*",
-        methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.DELETE, RequestMethod.PUT})
 @Api(value = "/training-definitions/{definitionId}/phase",
         tags = "Phases",
         consumes = MediaType.APPLICATION_JSON_VALUE,
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/QuestionnaireEvaluationController.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/QuestionnaireEvaluationController.java
deleted file mode 100644
index af9ae3971aade5f75d62481c6808ed1139dc2e07..0000000000000000000000000000000000000000
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/QuestionnaireEvaluationController.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package cz.muni.ics.kypo.training.adaptive.controller;
-
-import cz.muni.ics.kypo.training.adaptive.dto.run.QuestionnairePhaseAnswersDTO;
-import cz.muni.ics.kypo.training.adaptive.facade.QuestionnaireEvaluationFacade;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
-import io.swagger.annotations.Authorization;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.validation.Valid;
-
-@RestController
-@RequestMapping(value = "/training-runs", produces = MediaType.APPLICATION_JSON_VALUE)
-@CrossOrigin(origins = "*", allowCredentials = "true", allowedHeaders = "*",
-        methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.DELETE, RequestMethod.PUT})
-@Api(value = "/training-runs",
-        tags = "Training runs",
-        consumes = MediaType.APPLICATION_JSON_VALUE,
-        authorizations = @Authorization(value = "bearerAuth"))
-public class QuestionnaireEvaluationController {
-
-    private final QuestionnaireEvaluationFacade questionnaireEvaluationFacade;
-
-    @Autowired
-    public QuestionnaireEvaluationController(QuestionnaireEvaluationFacade questionnaireEvaluationFacade) {
-        this.questionnaireEvaluationFacade = questionnaireEvaluationFacade;
-    }
-
-    @ApiOperation(httpMethod = "POST",
-            value = "Evaluate answers to a questionnaire phase",
-            nickname = "evaluateAnswersToQuestionnaire",
-            produces = MediaType.APPLICATION_JSON_VALUE
-    )
-    @ApiResponses(value = {
-            @ApiResponse(code = 200, message = "Answers evaluated"),
-            @ApiResponse(code = 500, message = "Unexpected application error")
-    })
-    @PutMapping(value = "/{runId}/questionnaire-evaluation", produces = MediaType.APPLICATION_JSON_VALUE)
-    public ResponseEntity<Void> evaluateAnswersToQuestionnaire(@ApiParam(value = "Training run ID", required = true)
-                                                              @PathVariable("runId") Long runId,
-                                                              @ApiParam(value = "Responses to questionnaire", required = true)
-                                                              @Valid @RequestBody QuestionnairePhaseAnswersDTO questionnairePhaseAnswersDTO) {
-        questionnaireEvaluationFacade.evaluateAnswersToQuestionnaire(runId, questionnairePhaseAnswersDTO);
-        return ResponseEntity.noContent().build();
-    }
-}
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TasksController.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TasksController.java
index d3ad7e447b38fff389d841e1a5fc36a9006f9d17..c939708abc3a8dbc95c26bb9bf187b5352f1f2e0 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TasksController.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TasksController.java
@@ -15,8 +15,6 @@ import javax.validation.Valid;
 
 @RestController
 @RequestMapping(value = "/training-definitions/{definitionId}/phases/{phaseId}/tasks", produces = MediaType.APPLICATION_JSON_VALUE)
-@CrossOrigin(origins = "*", allowCredentials = "true", allowedHeaders = "*",
-        methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.DELETE, RequestMethod.PUT})
 @Api(value = "/training-definitions/{definitionId}/tasks",
         tags = "Tasks",
         consumes = MediaType.APPLICATION_JSON_VALUE,
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TrainingRunsRestController.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TrainingRunsRestController.java
index 83fe2059e8f757b1f1071abee2a51bdc16042f47..f3c7250a1acb12666789fdf2b49c3adb18aaed22 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TrainingRunsRestController.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/controller/TrainingRunsRestController.java
@@ -11,6 +11,7 @@ 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.UserRefDTO;
 import cz.muni.ics.kypo.training.adaptive.dto.responses.PageResultResource;
+import cz.muni.ics.kypo.training.adaptive.dto.run.QuestionnairePhaseAnswersDTO;
 import cz.muni.ics.kypo.training.adaptive.dto.training.ValidateAnswerDTO;
 import cz.muni.ics.kypo.training.adaptive.dto.trainingrun.AccessTrainingRunDTO;
 import cz.muni.ics.kypo.training.adaptive.dto.trainingrun.AccessedTrainingRunDTO;
@@ -358,30 +359,21 @@ public class TrainingRunsRestController {
         return ResponseEntity.ok().build();
     }
 
-    /**
-     * Evaluate responses to questionnaire.
-     *
-     * @param runId     id of training run.
-     * @param responses to questionnaire
-     * @return the response entity
-     */
     @ApiOperation(httpMethod = "PUT",
-            value = "Evaluate responses to questionnaire",
-            nickname = "evaluateResponsesToQuestionnaire",
+            value = "Evaluate answers to a questionnaire phase",
+            nickname = "evaluateAnswersToQuestionnaire",
             produces = MediaType.APPLICATION_JSON_VALUE
     )
     @ApiResponses(value = {
-            @ApiResponse(code = 204, message = "The responses to questionnaire has been evaluated and stored."),
-            @ApiResponse(code = 404, message = "The training run has not been found.", response = ApiError.class),
-            @ApiResponse(code = 409, message = "Current phase of training is not questionnaire phase or phase has been already answered.", response = ApiError.class),
-            @ApiResponse(code = 500, message = "Unexpected condition was encountered.", response = ApiError.class)
+            @ApiResponse(code = 200, message = "Answers evaluated"),
+            @ApiResponse(code = 500, message = "Unexpected application error")
     })
-    @PutMapping(value = "/{runId}/questionnaire-evaluations", produces = MediaType.APPLICATION_JSON_VALUE)
-    public ResponseEntity<Void> evaluateResponsesToQuestionnaire(@ApiParam(value = "Training run ID", required = true)
-                                                                 @PathVariable("runId") Long runId,
-                                                                 @ApiParam(value = "Responses to questionnaire", required = true)
-                                                                 @RequestBody String responses) {
-        trainingRunFacade.evaluateResponsesToQuestionnaire(runId, responses);
+    @PutMapping(value = "/{runId}/questionnaire-evaluation", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<Void> evaluateAnswersToQuestionnaire(@ApiParam(value = "Training run ID", required = true)
+                                                               @PathVariable("runId") Long runId,
+                                                               @ApiParam(value = "Responses to questionnaire", required = true)
+                                                               @Valid @RequestBody QuestionnairePhaseAnswersDTO questionnairePhaseAnswersDTO) {
+        trainingRunFacade.evaluateAnswersToQuestionnaire(runId, questionnairePhaseAnswersDTO);
         return ResponseEntity.noContent().build();
     }
 
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/phase/questions/Question.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/phase/questions/Question.java
index 9edf793159a89284be53f814665d69bef62de17e..cc6db3e32034cf9ff832dadc7ca58413e3e33c46 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/phase/questions/Question.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/phase/questions/Question.java
@@ -95,4 +95,19 @@ public class Question implements Serializable {
     public void addQuestionPhaseRelation(QuestionPhaseRelation questionPhaseRelation) {
         this.questionPhaseRelations.add(questionPhaseRelation);
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof Question)) return false;
+        Question question = (Question) o;
+        return getOrder() == question.getOrder() &&
+                getQuestionType() == question.getQuestionType() &&
+                Objects.equals(getText(), question.getText());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getQuestionType(), getText(), getOrder());
+    }
 }
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/QuestionAnswer.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/phase/questions/QuestionAnswer.java
similarity index 53%
rename from src/main/java/cz/muni/ics/kypo/training/adaptive/domain/QuestionAnswer.java
rename to src/main/java/cz/muni/ics/kypo/training/adaptive/domain/phase/questions/QuestionAnswer.java
index 211b904f7e0768cc2cce281416faaa17d605de1d..1e5a94bad9777acaa6b105dd34bf74180848c817 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/QuestionAnswer.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/phase/questions/QuestionAnswer.java
@@ -1,9 +1,12 @@
-package cz.muni.ics.kypo.training.adaptive.domain;
+package cz.muni.ics.kypo.training.adaptive.domain.phase.questions;
+
+import cz.muni.ics.kypo.training.adaptive.domain.UserRef;
 
 import javax.persistence.EmbeddedId;
 import javax.persistence.Entity;
 import javax.persistence.Table;
 import java.io.Serializable;
+import java.util.Objects;
 
 @Entity
 @Table(name = "question_answer")
@@ -11,7 +14,6 @@ public class QuestionAnswer implements Serializable {
 
     @EmbeddedId
     private QuestionAnswerId questionAnswerId;
-
     private String answer;
 
     public QuestionAnswerId getQuestionAnswerId() {
@@ -29,4 +31,18 @@ public class QuestionAnswer implements Serializable {
     public void setAnswer(String answer) {
         this.answer = answer;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof QuestionAnswer)) return false;
+        QuestionAnswer that = (QuestionAnswer) o;
+        return getQuestionAnswerId().equals(that.getQuestionAnswerId()) &&
+                getAnswer().equals(that.getAnswer());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getQuestionAnswerId(), getAnswer());
+    }
 }
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/QuestionAnswerId.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/phase/questions/QuestionAnswerId.java
similarity index 65%
rename from src/main/java/cz/muni/ics/kypo/training/adaptive/domain/QuestionAnswerId.java
rename to src/main/java/cz/muni/ics/kypo/training/adaptive/domain/phase/questions/QuestionAnswerId.java
index d59dff5ccdf7b39773de264a7dd56601a3d582d7..71b48ba66fc64aed2559f537b262dbacaad560f4 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/QuestionAnswerId.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/phase/questions/QuestionAnswerId.java
@@ -1,11 +1,19 @@
-package cz.muni.ics.kypo.training.adaptive.domain;
+package cz.muni.ics.kypo.training.adaptive.domain.phase.questions;
+
+import cz.muni.ics.kypo.training.adaptive.domain.TRAcquisitionLock;
 
 import javax.persistence.Embeddable;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
 import java.io.Serializable;
 import java.util.Objects;
 
 @Embeddable
 public class QuestionAnswerId implements Serializable {
+
+    @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "question_id")
     private Question question;
     private Long trainingRunId;
 
@@ -36,10 +44,11 @@ public class QuestionAnswerId implements Serializable {
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
+        if (!(o instanceof QuestionAnswerId))
+            return false;
         QuestionAnswerId that = (QuestionAnswerId) o;
-        return Objects.equals(question, that.question) &&
-                Objects.equals(trainingRunId, that.trainingRunId);
+        return getQuestion().equals(that.getQuestion()) &&
+                getTrainingRunId().equals(that.getTrainingRunId());
     }
 
     @Override
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/QuestionPhaseResult.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/phase/questions/QuestionPhaseResult.java
similarity index 78%
rename from src/main/java/cz/muni/ics/kypo/training/adaptive/domain/QuestionPhaseResult.java
rename to src/main/java/cz/muni/ics/kypo/training/adaptive/domain/phase/questions/QuestionPhaseResult.java
index cfc2bf0de2ab73fc2c22897f37d35d228092bcb3..034a16594221085c65827681f03b22ccb068a53f 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/QuestionPhaseResult.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/phase/questions/QuestionPhaseResult.java
@@ -1,14 +1,7 @@
-package cz.muni.ics.kypo.training.adaptive.domain;
-
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.ManyToOne;
-import javax.persistence.SequenceGenerator;
-import javax.persistence.Table;
+package cz.muni.ics.kypo.training.adaptive.domain.phase.questions;
+
+
+import javax.persistence.*;
 import java.io.Serializable;
 
 @Entity
@@ -25,6 +18,7 @@ public class QuestionPhaseResult implements Serializable {
     private int achievedResult;
 
     @ManyToOne(fetch = FetchType.LAZY)
+    @JoinColumn(name = "question_phase_relation_id")
     private QuestionPhaseRelation questionPhaseRelation;
 
     public Long getId() {
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/training/TrainingRun.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/training/TrainingRun.java
index 95acdfb77bc62b175e916b242aea200528e3d078..42a8bc2bffd4a97c52d484f46056ed0d3d014c83 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/training/TrainingRun.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/domain/training/TrainingRun.java
@@ -120,10 +120,6 @@ public class TrainingRun extends AbstractEntity<Long> {
     @ManyToOne(fetch = FetchType.LAZY)
     @JoinColumn(name = "user_ref_id", nullable = false)
     private UserRef participantRef;
-    @Lob
-    @Type(type = "org.hibernate.type.TextType")
-    @Column(name = "questionnaire_responses", nullable = true)
-    private String questionnaireResponses;
     @Column(name = "phase_answered")
     private boolean phaseAnswered;
     @Column(name = "previous_sandbox_instance_ref_id")
@@ -304,24 +300,6 @@ public class TrainingRun extends AbstractEntity<Long> {
         this.solutionTaken = solutionTaken;
     }
 
-    /**
-     * Gets responses of current assessment phase
-     *
-     * @return the assessment responses
-     */
-    public String getQuestionnaireResponses() {
-        return questionnaireResponses;
-    }
-
-    /**
-     * Sets responses of current assessment phase
-     *
-     * @param assessmentResponses the assessment responses
-     */
-    public void setQuestionnaireResponses(String assessmentResponses) {
-        this.questionnaireResponses = assessmentResponses;
-    }
-
     /**
      * Gets DB reference of trainee
      *
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/facade/QuestionnaireEvaluationFacade.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/facade/QuestionnaireEvaluationFacade.java
deleted file mode 100644
index fd657740cb375d2aaef4ec50eb08794d848af01a..0000000000000000000000000000000000000000
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/facade/QuestionnaireEvaluationFacade.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package cz.muni.ics.kypo.training.adaptive.facade;
-
-import cz.muni.ics.kypo.training.adaptive.domain.QuestionAnswer;
-import cz.muni.ics.kypo.training.adaptive.dto.run.QuestionnairePhaseAnswersDTO;
-import cz.muni.ics.kypo.training.adaptive.service.QuestionnaireEvaluationService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-@Service
-public class QuestionnaireEvaluationFacade {
-
-    private final QuestionnaireEvaluationService questionnaireEvaluationService;
-
-    @Autowired
-    public QuestionnaireEvaluationFacade(QuestionnaireEvaluationService questionnaireEvaluationService) {
-        this.questionnaireEvaluationService = questionnaireEvaluationService;
-    }
-
-    public void evaluateAnswersToQuestionnaire(Long runId, QuestionnairePhaseAnswersDTO questionnairePhaseAnswersDTO) {
-        List<QuestionAnswer> savedAnswers = questionnaireEvaluationService.saveAnswersToQuestionnaire(runId, questionnairePhaseAnswersDTO);
-        questionnaireEvaluationService.evaluateAnswersToQuestionnaire(runId, savedAnswers);
-    }
-}
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/facade/TrainingRunFacade.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/facade/TrainingRunFacade.java
index 980b96fb6d86a0f617678abc2f5c4fedeaaa1a24..dbc54add237e913852b8084f984b37040463dc10 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/facade/TrainingRunFacade.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/facade/TrainingRunFacade.java
@@ -20,6 +20,8 @@ import cz.muni.ics.kypo.training.adaptive.dto.questionnaire.QuestionChoiceDTO;
 import cz.muni.ics.kypo.training.adaptive.dto.questionnaire.QuestionDTO;
 import cz.muni.ics.kypo.training.adaptive.dto.questionnaire.QuestionnairePhaseDTO;
 import cz.muni.ics.kypo.training.adaptive.dto.responses.PageResultResource;
+import cz.muni.ics.kypo.training.adaptive.dto.run.QuestionAnswerDTO;
+import cz.muni.ics.kypo.training.adaptive.dto.run.QuestionnairePhaseAnswersDTO;
 import cz.muni.ics.kypo.training.adaptive.dto.trainingrun.AccessTrainingRunDTO;
 import cz.muni.ics.kypo.training.adaptive.dto.trainingrun.AccessedTrainingRunDTO;
 import cz.muni.ics.kypo.training.adaptive.dto.trainingrun.TrainingRunByIdDTO;
@@ -28,8 +30,7 @@ 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.mapstruct.PhaseMapper;
 import cz.muni.ics.kypo.training.adaptive.mapping.mapstruct.TrainingRunMapper;
-import cz.muni.ics.kypo.training.adaptive.service.SecurityService;
-import cz.muni.ics.kypo.training.adaptive.service.UserService;
+import cz.muni.ics.kypo.training.adaptive.service.QuestionnaireEvaluationService;
 import cz.muni.ics.kypo.training.adaptive.service.api.UserManagementServiceApi;
 import cz.muni.ics.kypo.training.adaptive.service.training.TrainingRunService;
 import org.slf4j.Logger;
@@ -43,10 +44,8 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.time.Clock;
 import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * The type Training run facade.
@@ -56,29 +55,29 @@ public class TrainingRunFacade {
 
     private static final Logger LOG = LoggerFactory.getLogger(TrainingRunFacade.class);
 
-    private TrainingRunService trainingRunService;
-    private UserService userService;
-    private UserManagementServiceApi userManagementServiceApi;
-    private TrainingRunMapper trainingRunMapper;
-    private PhaseMapper phaseMapper;
+    private final TrainingRunService trainingRunService;
+    private final UserManagementServiceApi userManagementServiceApi;
+    private final TrainingRunMapper trainingRunMapper;
+    private final PhaseMapper phaseMapper;
+    private final QuestionnaireEvaluationService questionnaireEvaluationService;
+
 
 
     /**
      * Instantiates a new Training run facade.
      *
      * @param trainingRunService the training run service
-     * @param userService        the user service
      * @param trainingRunMapper  the training run mapper
      * @param phaseMapper        the phase mapper
      */
     @Autowired
     public TrainingRunFacade(TrainingRunService trainingRunService,
-                             UserService userService,
+                             QuestionnaireEvaluationService questionnaireEvaluationService,
                              UserManagementServiceApi userManagementServiceApi,
                              TrainingRunMapper trainingRunMapper,
                              PhaseMapper phaseMapper) {
         this.trainingRunService = trainingRunService;
-        this.userService = userService;
+        this.questionnaireEvaluationService = questionnaireEvaluationService;
         this.userManagementServiceApi = userManagementServiceApi;
         this.trainingRunMapper = trainingRunMapper;
         this.phaseMapper = phaseMapper;
@@ -334,15 +333,18 @@ public class TrainingRunFacade {
     }
 
     /**
-     * Evaluate and store responses to questionnaire.
+     * Evaluate and store answers to questionnaire.
      *
-     * @param trainingRunId     id of Training Run to be finish.
-     * @param responsesAsString responses to questionnaire
+     * @param trainingRunId     id of the Training Run.
+     * @param questionnairePhaseAnswersDTO answers to questionnaire
      */
-    @IsTrainee
+    @PreAuthorize("hasAuthority(T(cz.muni.ics.kypo.training.adaptive.enums.RoleTypeSecurity).ROLE_ADAPTIVE_TRAINING_ADMINISTRATOR)" +
+            "or @securityService.isTraineeOfGivenTrainingRun(#trainingRunId)")
     @TransactionalWO
-    public void evaluateResponsesToQuestionnaire(Long trainingRunId, String responsesAsString) {
-        trainingRunService.evaluateResponsesToQuestionnaire(trainingRunId, responsesAsString);
+    public void evaluateAnswersToQuestionnaire(Long trainingRunId, QuestionnairePhaseAnswersDTO questionnairePhaseAnswersDTO) {
+        Map<Long, String> questionsAnswersMapping = questionnairePhaseAnswersDTO.getAnswers().stream()
+                .collect(Collectors.toMap(QuestionAnswerDTO::getQuestionId, QuestionAnswerDTO::getAnswer));
+        questionnaireEvaluationService.saveAndEvaluateAnswersToQuestionnaire(trainingRunId, questionsAnswersMapping);
     }
 
     /**
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/QuestionAnswerRepository.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/QuestionAnswerRepository.java
index 2c5e54e8ab08423f376c53b068f9768672a78e02..8fc46323af5d8daa8f9adc1ab6a3908cae6b8229 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/QuestionAnswerRepository.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/QuestionAnswerRepository.java
@@ -1,7 +1,7 @@
 package cz.muni.ics.kypo.training.adaptive.repository;
 
-import cz.muni.ics.kypo.training.adaptive.domain.QuestionAnswer;
-import cz.muni.ics.kypo.training.adaptive.domain.QuestionAnswerId;
+import cz.muni.ics.kypo.training.adaptive.domain.phase.questions.QuestionAnswer;
+import cz.muni.ics.kypo.training.adaptive.domain.phase.questions.QuestionAnswerId;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.stereotype.Repository;
 
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/QuestionPhaseResultRepository.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/QuestionPhaseResultRepository.java
index 86c9945d90e33876ca59d3496d20309ee5264a90..6c417b061364af17e29da234883b711c6793cd6b 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/QuestionPhaseResultRepository.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/QuestionPhaseResultRepository.java
@@ -1,6 +1,6 @@
 package cz.muni.ics.kypo.training.adaptive.repository;
 
-import cz.muni.ics.kypo.training.adaptive.domain.QuestionPhaseResult;
+import cz.muni.ics.kypo.training.adaptive.domain.phase.questions.QuestionPhaseResult;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.stereotype.Repository;
 
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/phases/QuestionRepository.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/phases/QuestionRepository.java
index 2e2ceb2bb1ad1b4501b14b4966c87323a6fc30ed..c6aad8d64a6f52db57497b526016879f8aac1deb 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/phases/QuestionRepository.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/repository/phases/QuestionRepository.java
@@ -4,6 +4,10 @@ import cz.muni.ics.kypo.training.adaptive.domain.phase.questions.Question;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.stereotype.Repository;
 
+import java.util.Optional;
+
 @Repository
 public interface QuestionRepository extends JpaRepository<Question, Long> {
+
+    Optional<Question> findByIdAndQuestionnairePhaseId(Long questionId, Long questionnaireId);
 }
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/service/QuestionnaireEvaluationService.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/service/QuestionnaireEvaluationService.java
index c1d70ef79527c3377621353cc11f78aded7e8ddc..ad097254a2b4cb6699ad74ed885aace649fc14e3 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/service/QuestionnaireEvaluationService.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/service/QuestionnaireEvaluationService.java
@@ -1,33 +1,29 @@
 package cz.muni.ics.kypo.training.adaptive.service;
 
-import cz.muni.ics.kypo.training.adaptive.domain.Question;
-import cz.muni.ics.kypo.training.adaptive.domain.QuestionAnswer;
-import cz.muni.ics.kypo.training.adaptive.domain.QuestionAnswerId;
-import cz.muni.ics.kypo.training.adaptive.domain.QuestionChoice;
-import cz.muni.ics.kypo.training.adaptive.domain.QuestionPhaseRelation;
-import cz.muni.ics.kypo.training.adaptive.domain.QuestionPhaseResult;
-import cz.muni.ics.kypo.training.adaptive.dto.run.QuestionAnswerDTO;
-import cz.muni.ics.kypo.training.adaptive.dto.run.QuestionnairePhaseAnswersDTO;
+import cz.muni.ics.kypo.training.adaptive.domain.phase.QuestionnairePhase;
+import cz.muni.ics.kypo.training.adaptive.domain.phase.questions.*;
+import cz.muni.ics.kypo.training.adaptive.domain.training.TrainingRun;
+import cz.muni.ics.kypo.training.adaptive.enums.QuestionnaireType;
+import cz.muni.ics.kypo.training.adaptive.exceptions.BadRequestException;
+import cz.muni.ics.kypo.training.adaptive.exceptions.EntityConflictException;
+import cz.muni.ics.kypo.training.adaptive.exceptions.EntityErrorDetail;
+import cz.muni.ics.kypo.training.adaptive.exceptions.EntityNotFoundException;
 import cz.muni.ics.kypo.training.adaptive.repository.QuestionAnswerRepository;
-import cz.muni.ics.kypo.training.adaptive.repository.QuestionPhaseRelationRepository;
 import cz.muni.ics.kypo.training.adaptive.repository.QuestionPhaseResultRepository;
-import cz.muni.ics.kypo.training.adaptive.repository.QuestionRepository;
+import cz.muni.ics.kypo.training.adaptive.repository.phases.QuestionPhaseRelationRepository;
+import cz.muni.ics.kypo.training.adaptive.repository.phases.QuestionRepository;
+import cz.muni.ics.kypo.training.adaptive.repository.training.TrainingRunRepository;
+import cz.muni.ics.kypo.training.adaptive.service.audit.AuditEventsService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Service
-@Transactional
 public class QuestionnaireEvaluationService {
 
     private static final Logger LOG = LoggerFactory.getLogger(QuestionnaireEvaluationService.class);
@@ -36,35 +32,70 @@ public class QuestionnaireEvaluationService {
     private final QuestionAnswerRepository questionAnswerRepository;
     private final QuestionPhaseRelationRepository questionPhaseRelationRepository;
     private final QuestionPhaseResultRepository questionPhaseResultRepository;
+    private final TrainingRunRepository trainingRunRepository;
+    private final AuditEventsService auditEventsService;
 
     @Autowired
-    public QuestionnaireEvaluationService(QuestionRepository questionRepository, QuestionAnswerRepository questionAnswerRepository,
-                                          QuestionPhaseRelationRepository questionPhaseRelationRepository, QuestionPhaseResultRepository questionPhaseResultRepository) {
+    public QuestionnaireEvaluationService(QuestionRepository questionRepository,
+                                          QuestionAnswerRepository questionAnswerRepository,
+                                          QuestionPhaseRelationRepository questionPhaseRelationRepository,
+                                          QuestionPhaseResultRepository questionPhaseResultRepository,
+                                          TrainingRunRepository trainingRunRepository,
+                                          AuditEventsService auditEventsService) {
         this.questionRepository = questionRepository;
         this.questionAnswerRepository = questionAnswerRepository;
         this.questionPhaseRelationRepository = questionPhaseRelationRepository;
         this.questionPhaseResultRepository = questionPhaseResultRepository;
+        this.trainingRunRepository = trainingRunRepository;
+        this.auditEventsService = auditEventsService;
     }
 
-    public List<QuestionAnswer> saveAnswersToQuestionnaire(Long runId, QuestionnairePhaseAnswersDTO questionnairePhaseAnswersDTO) {
-        List<QuestionAnswer> result = new ArrayList<>();
-        for (QuestionAnswerDTO answer : questionnairePhaseAnswersDTO.getAnswers()) {
-            Question question = questionRepository.findById(answer.getQuestionId())
-                    .orElseThrow(() -> new RuntimeException("Question was not found"));
-            // TODO throw proper exception once kypo2-training is migrated
-
-            QuestionAnswer questionAnswer = new QuestionAnswer();
-            questionAnswer.setQuestionAnswerId(new QuestionAnswerId(question, runId));
-            questionAnswer.setAnswer(answer.getAnswer());
+    /**
+     * Evaluate and store answers to questionnaire.
+     *
+     * @param trainingRunId     id of training run to answer the questionnaire.
+     * @param questionnairePhaseAnswers answers to questionnaire to be evaluated. Map of entries (Key = question ID, Value = answer).
+     * @throws EntityNotFoundException training run is not found.
+     */
+    public List<QuestionAnswer> saveAndEvaluateAnswersToQuestionnaire(Long trainingRunId, Map<Long, String> questionnairePhaseAnswers) {
+        TrainingRun trainingRun = this.findByIdWithPhase(trainingRunId);
+        this.checkIfCanBeEvaluated(trainingRun);
+
+        List<QuestionAnswer> storedQuestionsAnswers = new ArrayList<>();
+        for (Map.Entry<Long, String> questionAnswer : questionnairePhaseAnswers.entrySet()) {
+            Long questionnaireId = trainingRun.getCurrentPhase().getId();
+            storedQuestionsAnswers.add(saveQuestionAnswer(questionAnswer.getKey(), questionAnswer.getValue(), questionnaireId, trainingRun.getId()));
+        }
+        if (((QuestionnairePhase) trainingRun.getCurrentPhase()).getQuestionnaireType() == QuestionnaireType.ADAPTIVE) {
+            this.evaluateAnswersToQuestionnaire(trainingRunId, storedQuestionsAnswers);
+        }
+        auditEventsService.auditPhaseCompletedAction(trainingRun);
+        auditEventsService.auditQuestionnaireAnswersAction(trainingRun, storedQuestionsAnswers.stream()
+                .collect(Collectors.toMap(questionAnswer -> questionAnswer.getQuestionAnswerId().getQuestion().getText(), QuestionAnswer::getAnswer))
+                .toString());
+        trainingRun.setPhaseAnswered(true);
+        return storedQuestionsAnswers;
+    }
 
-            questionAnswerRepository.save(questionAnswer);
-            result.add(questionAnswer);
+    private void checkIfCanBeEvaluated(TrainingRun trainingRun) {
+        if (!(trainingRun.getCurrentPhase() instanceof QuestionnairePhase)) {
+            throw new BadRequestException("Current phase is not questionnaire phase and cannot be evaluated.");
         }
+        if (trainingRun.isPhaseAnswered())
+            throw new EntityConflictException(new EntityErrorDetail(TrainingRun.class, "id", Long.class, trainingRun.getId(),
+                    "Current phase of the training run has been already answered."));
+    }
 
-        return result;
+    private QuestionAnswer saveQuestionAnswer(Long questionId, String answer, Long questionnaireId, Long trainingRunId) {
+        Question question = this.findQuestionByIdAndQuestionnairePhaseId(questionId, questionnaireId);
+        QuestionAnswer questionAnswer = new QuestionAnswer();
+        questionAnswer.setQuestionAnswerId(new QuestionAnswerId(question, trainingRunId));
+        questionAnswer.setAnswer(answer);
+
+        return questionAnswerRepository.save(questionAnswer);
     }
 
-    public void evaluateAnswersToQuestionnaire(Long runId, List<QuestionAnswer> answers) {
+    private void evaluateAnswersToQuestionnaire(Long runId, List<QuestionAnswer> answers) {
         if (CollectionUtils.isEmpty(answers)) {
             return;
         }
@@ -118,4 +149,14 @@ public class QuestionnaireEvaluationService {
                 .filter(q -> Objects.equals(answer, q.getText()))
                 .findFirst();
     }
+
+    private TrainingRun findByIdWithPhase(Long runId) {
+        return trainingRunRepository.findByIdWithPhase(runId).orElseThrow(() -> new EntityNotFoundException(
+                new EntityErrorDetail(TrainingRun.class, "id", runId.getClass(), runId)));
+    }
+
+    private Question findQuestionByIdAndQuestionnairePhaseId(Long questionId, Long questionnaireId) {
+        return questionRepository.findByIdAndQuestionnairePhaseId(questionId, questionnaireId)
+                .orElseThrow(() -> new EntityNotFoundException(new EntityErrorDetail(Question.class, "id", Long.class, questionId)));
+    }
 }
diff --git a/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingRunService.java b/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingRunService.java
index f19241709c6c7bd01ebc9a4f683e557de1c71a94..88d7e2cabda9342d79f3fd2e35e8db90cef040a6 100644
--- a/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingRunService.java
+++ b/src/main/java/cz/muni/ics/kypo/training/adaptive/service/training/TrainingRunService.java
@@ -60,7 +60,7 @@ public class TrainingRunService {
      * @param trainingInstanceRepository  the training instance repository
      * @param participantRefRepository    the participant ref repository
      * @param auditEventsService          the audit events service
-     * @param securityService             the security service
+     * @param sandboxServiceApi           the sandbox service api
      * @param trAcquisitionLockRepository the tr acquisition lock repository
      */
     @Autowired
@@ -322,7 +322,6 @@ public class TrainingRunService {
         } else {
             newTrainingRun.setParticipantRef(participantRefRepository.save(new UserRef(userManagementServiceApi.getLoggedInUserRefId())));
         }
-        newTrainingRun.setQuestionnaireResponses("[]");
         newTrainingRun.setState(TRState.RUNNING);
         newTrainingRun.setTrainingInstance(trainingInstance);
         newTrainingRun.setStartTime(startTime);
@@ -501,13 +500,7 @@ public class TrainingRunService {
         trainingRunRepository.save(trainingRun);
     }
 
-    /**
-     * Evaluate and store responses to questionnaire.
-     *
-     * @param trainingRunId     id of training run to be finished.
-     * @param responsesAsString response to questionnaire to be evaluated
-     * @throws EntityNotFoundException training run is not found.
-     */
+
     public void evaluateResponsesToQuestionnaire(Long trainingRunId, String responsesAsString) {
         TrainingRun trainingRun = findByIdWithPhase(trainingRunId);
         if (!(trainingRun.getCurrentPhase() instanceof QuestionnairePhase)) {
diff --git a/src/main/resources/db/migration/V1__db_adaptive_trainings_schema.sql b/src/main/resources/db/migration/V1__db_adaptive_trainings_schema.sql
index 43bbe615f9acb9e3a7bd6aecfee6ccaaf533655f..14d59308693f6666ec71a7432dff0dc4adb012c5 100644
--- a/src/main/resources/db/migration/V1__db_adaptive_trainings_schema.sql
+++ b/src/main/resources/db/migration/V1__db_adaptive_trainings_schema.sql
@@ -172,6 +172,25 @@ create table question_phase_relation_question (
     foreign key (question_id) references question
 );
 
+create table question_answer (
+    question_id  int8 not null,
+    training_run_id int8 not null,
+    answer varchar(255) not null,
+    primary key (question_id, training_run_id),
+    foreign key (question_id) references question,
+    foreign key (training_run_id) references training_run,
+    unique (question_id, training_run_id)
+);
+
+create table question_phase_result (
+    question_phase_result_id  bigserial not null,
+    training_run_id int8 not null,
+    question_phase_relation_id int8 not null,
+    achieved_result int4 not null,
+    primary key (question_phase_result_id),
+    foreign key (question_phase_relation_id) references question_phase_relation
+);
+
 -- ACCESS TOKEN
 create table access_token (
    id  bigserial not null,
diff --git a/src/main/resources/db/migration/V2__db_adaptive_trainings_sequences.sql b/src/main/resources/db/migration/V2__db_adaptive_trainings_sequences.sql
index 5f55c926c77fe2ef7849167902e332e517d74637..1f09c3ec2cac7ee24056a160d89858508c825b28 100644
--- a/src/main/resources/db/migration/V2__db_adaptive_trainings_sequences.sql
+++ b/src/main/resources/db/migration/V2__db_adaptive_trainings_sequences.sql
@@ -4,3 +4,4 @@ CREATE SEQUENCE question_seq AS bigint INCREMENT 50 MINVALUE 1;
 CREATE SEQUENCE question_choice_seq AS bigint INCREMENT 50 MINVALUE 1;
 CREATE SEQUENCE question_phase_seq AS bigint INCREMENT 50 MINVALUE 1;
 CREATE SEQUENCE decision_matrix_row_seq AS bigint INCREMENT 50 MINVALUE 1;
+CREATE SEQUENCE question_phase_result_seq AS bigint INCREMENT 50 MINVALUE 1;
diff --git a/src/test/java/cz/muni/ics/kypo/training/adaptive/DemoApplicationTests.java b/src/test/java/cz/muni/ics/kypo/training/adaptive/AdaptiveTrainingApplicationTests.java
similarity index 86%
rename from src/test/java/cz/muni/ics/kypo/training/adaptive/DemoApplicationTests.java
rename to src/test/java/cz/muni/ics/kypo/training/adaptive/AdaptiveTrainingApplicationTests.java
index 53d7b0d9f3dca61608a2618b7c3b75c0bec1c5f1..df77eecfaf85d71e1e440c477d13a356f8393670 100644
--- a/src/test/java/cz/muni/ics/kypo/training/adaptive/DemoApplicationTests.java
+++ b/src/test/java/cz/muni/ics/kypo/training/adaptive/AdaptiveTrainingApplicationTests.java
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.context.SpringBootTest;
 
 @SpringBootTest(classes = TestAdaptiveTrainingConfiguration.class)
-class DemoApplicationTests {
+class AdaptiveTrainingApplicationTests {
 
     @Test
     void contextLoads() {