diff options
| author | Szymon Szukalski <szymon@skas.io> | 2024-07-25 20:36:11 +1000 |
|---|---|---|
| committer | Szymon Szukalski <szymon@skas.io> | 2024-07-25 20:36:11 +1000 |
| commit | aa9bdd514ab90d0da0391b879255a22c29450e9a (patch) | |
| tree | 9ddd1de0ab7e376ead06f55bdb32a6190d3647d5 /src/main/java/com/stileeducation/markr/controller | |
| parent | ec81d98e90f9fdb4dd12138a365fbbbb3a8efa5f (diff) | |
Validate import payload and return create/update stats
- Add validation to /import payload
- Move import logic to service bean
- Track whether entities have been created or update
- Report number of created and updated entities as return value for the
import endpoint
- Add some test coverage to exercise the validators
Diffstat (limited to 'src/main/java/com/stileeducation/markr/controller')
| -rw-r--r-- | src/main/java/com/stileeducation/markr/controller/TestResultsController.java | 129 |
1 files changed, 61 insertions, 68 deletions
diff --git a/src/main/java/com/stileeducation/markr/controller/TestResultsController.java b/src/main/java/com/stileeducation/markr/controller/TestResultsController.java index 1376ecb..f5b6070 100644 --- a/src/main/java/com/stileeducation/markr/controller/TestResultsController.java +++ b/src/main/java/com/stileeducation/markr/controller/TestResultsController.java @@ -1,11 +1,8 @@ package com.stileeducation.markr.controller; -import com.stileeducation.markr.dto.AggregatedTestResultsDTO; -import com.stileeducation.markr.dto.MCQTestResultDTO; +import com.stileeducation.markr.dto.AggregateResponseDTO; +import com.stileeducation.markr.dto.ImportResponseDTO; import com.stileeducation.markr.dto.MCQTestResultsDTO; -import com.stileeducation.markr.entity.Student; -import com.stileeducation.markr.entity.Test; -import com.stileeducation.markr.entity.TestResult; import com.stileeducation.markr.repository.TestRepository; import com.stileeducation.markr.repository.TestResultRepository; import com.stileeducation.markr.service.StudentService; @@ -14,81 +11,77 @@ import com.stileeducation.markr.service.TestService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/") public class TestResultsController { - public static final String IMPORT_ENDPOINT = "/import"; - public static final String AGGREGATE_ENDPOINT = "/results/{test-id}/aggregate"; + public static final String IMPORT_ENDPOINT = "/import"; + public static final String AGGREGATE_ENDPOINT = "/results/{test-id}/aggregate"; - @Autowired - private StudentService studentService; + @Autowired + private StudentService studentService; - @Autowired - private TestService testService; + @Autowired + private TestService testService; - @Autowired - private TestResultsService testResultsService; + @Autowired + private TestResultsService testResultsService; - @Autowired - private TestRepository testRepository; + @Autowired + private TestRepository testRepository; - @Autowired - private TestResultRepository testResultRepository; + @Autowired + private TestResultRepository testResultRepository; - public TestResultsController(TestResultsService testResultsService) { - this.testResultsService = testResultsService; - } - - // TODO consider return value - @PostMapping( - value = IMPORT_ENDPOINT, - consumes = "text/xml+markr", - produces = "application/json") - public ResponseEntity<Void> handleXmlRequest(@RequestBody MCQTestResultsDTO testResults) { - - for (MCQTestResultDTO mcqTestResult : testResults.getMcqTestResults()) { - Student student = studentService - .findOrCreateStudent( - mcqTestResult.getFirstName(), - mcqTestResult.getLastName(), - mcqTestResult.getStudentNumber()); - - Test test = testService - .findOrCreateTest( - mcqTestResult.getTestId(), - mcqTestResult.getSummaryMarks().getAvailable()); - - if (test.getMarksAvailable() < mcqTestResult.getSummaryMarks().getAvailable()) { - test.setMarksAvailable(mcqTestResult.getSummaryMarks().getAvailable()); - testRepository.save(test); - } - - // Some edge cases to consider - // obtained is higher than available (assumption?) + public TestResultsController(TestResultsService testResultsService) { + this.testResultsService = testResultsService; + } - TestResult testResult = testResultsService - .findOrCreateTestResult( - student.getId(), - test.getId(), - mcqTestResult.getSummaryMarks().getObtained()); - - if (testResult.getMarksAwarded() < mcqTestResult.getSummaryMarks().getObtained()) { - testResult.setMarksAwarded(mcqTestResult.getSummaryMarks().getObtained()); - testResultRepository.save(testResult); - } - } - - return new ResponseEntity<>(HttpStatus.NO_CONTENT); + @PostMapping( + value = IMPORT_ENDPOINT, + consumes = "text/xml+markr", + produces = "application/json") + public ResponseEntity<ImportResponseDTO> postTestResults(@Validated @RequestBody MCQTestResultsDTO testResults) { + ImportResponseDTO response = testResultsService.processTestResults(testResults); + if ("failure".equals(response.getStatus())) { + return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); } - - @GetMapping( - value = AGGREGATE_ENDPOINT, - produces = "application/json") - public AggregatedTestResultsDTO getAggregatedResults(@PathVariable("test-id") String testId) { - return testResultsService.aggregateTestResults(testId); - } - + return new ResponseEntity<>(response, HttpStatus.OK); + } + + @GetMapping( + value = AGGREGATE_ENDPOINT, + produces = "application/json") + public AggregateResponseDTO getAggregatedResults(@PathVariable("test-id") String testId) { + return testResultsService.aggregateTestResults(testId); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity<ImportResponseDTO> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) { + ImportResponseDTO response = new ImportResponseDTO(); + response.setStatus("error"); + response.setMessage("Invalid payload"); + return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler(HttpMessageNotReadableException.class) + public ResponseEntity<ImportResponseDTO> handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) { + ImportResponseDTO response = new ImportResponseDTO(); + response.setStatus("error"); + response.setMessage("Invalid XML payload"); + return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity<ImportResponseDTO> handleGenericException(Exception ex) { + ImportResponseDTO response = new ImportResponseDTO(); + response.setStatus("error"); + response.setMessage("An unexpected error occurred"); + return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR); + } } |
