diff --git a/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java b/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java index 01bd18e7..3b056efb 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java +++ b/src/main/java/ch/ethz/seb/sebserver/gbl/api/APIMessage.java @@ -43,9 +43,9 @@ public class APIMessage implements Serializable { RESOURCE_NOT_FOUND("1002", HttpStatus.NOT_FOUND, "resource not found"), ILLEGAL_API_ARGUMENT("1010", HttpStatus.BAD_REQUEST, "Illegal API request argument"), UNEXPECTED("1100", HttpStatus.INTERNAL_SERVER_ERROR, "Unexpected internal server-side error"), + INTEGRITY_VALIDATION("1101", HttpStatus.BAD_REQUEST, "Action would lied to an integrity violation"), FIELD_VALIDATION("1200", HttpStatus.BAD_REQUEST, "Field validation error"), - INTEGRITY_VALIDATION("1201", HttpStatus.BAD_REQUEST, "Action would lied to an integrity violation"), PASSWORD_MISMATCH("1300", HttpStatus.BAD_REQUEST, "new password do not match confirmed password"), MISSING_PASSWORD("1301", HttpStatus.BAD_REQUEST, "Missing Password"), diff --git a/src/main/java/ch/ethz/seb/sebserver/gui/content/configs/SEBExamConfigForm.java b/src/main/java/ch/ethz/seb/sebserver/gui/content/configs/SEBExamConfigForm.java index e99c0f83..de4b8f57 100644 --- a/src/main/java/ch/ethz/seb/sebserver/gui/content/configs/SEBExamConfigForm.java +++ b/src/main/java/ch/ethz/seb/sebserver/gui/content/configs/SEBExamConfigForm.java @@ -27,6 +27,7 @@ import ch.ethz.seb.sebserver.gbl.api.EntityType; import ch.ethz.seb.sebserver.gbl.model.Domain; import ch.ethz.seb.sebserver.gbl.model.EntityKey; import ch.ethz.seb.sebserver.gbl.model.EntityProcessingReport; +import ch.ethz.seb.sebserver.gbl.model.Page; import ch.ethz.seb.sebserver.gbl.model.exam.Exam.ExamStatus; import ch.ethz.seb.sebserver.gbl.model.exam.ExamConfigurationMap; import ch.ethz.seb.sebserver.gbl.model.exam.QuizData; @@ -179,16 +180,24 @@ public class SEBExamConfigForm implements TemplateComposer { .call() .map(names -> names != null && !names.isEmpty()) .getOr(Boolean.FALSE); - final boolean hasRunningExam = isAttachedToExam && this.restService + final Result> examsPage = this.restService .getBuilder(GetExamConfigMappingsPage.class) .withQueryParam(ExamConfigurationMap.FILTER_ATTR_CONFIG_ID, examConfig.getModelId()) - .call() + .call(); + final boolean hasRunningExam = isAttachedToExam && examsPage .map(res -> res.content .stream() .filter(map -> map.examStatus == ExamStatus.RUNNING) .findAny() .isPresent()) .getOr(false); + final boolean hasActiveExams = hasRunningExam || examsPage + .map(res -> res.content + .stream() + .filter(map -> map.examStatus == ExamStatus.UP_COMING) + .findAny() + .isPresent()) + .getOr(false); // new PageContext with actual EntityKey final PageContext formContext = pageContext.withEntityKey(examConfig.getEntityKey()); @@ -261,7 +270,7 @@ public class SEBExamConfigForm implements TemplateComposer { Domain.CONFIGURATION_NODE.ATTR_STATUS, FORM_STATUS_TEXT_KEY, examConfig.status.name(), - () -> resourceService.examConfigStatusResources(isAttachedToExam, hasRunningExam)) + () -> resourceService.examConfigStatusResources(isAttachedToExam, hasActiveExams)) .withEmptyCellSeparation(!isReadonly)) .buildFor((isNew) ? this.restService.getRestCall(NewExamConfig.class) diff --git a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java index 769eba14..2eb7793e 100644 --- a/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java +++ b/src/main/java/ch/ethz/seb/sebserver/webservice/servicelayer/dao/impl/ExamConfigurationMapDAOImpl.java @@ -66,8 +66,8 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.dao.TransactionHandler; public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO { private static final List ACTIVE_EXAM_STATE_NAMES = Arrays.asList( - ExamStatus.FINISHED.name(), - ExamStatus.ARCHIVED.name()); + ExamStatus.UP_COMING.name(), + ExamStatus.RUNNING.name()); private final ExamRecordMapper examRecordMapper; private final ExamConfigurationMapRecordMapper examConfigurationMapRecordMapper; @@ -382,7 +382,7 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO { @Override @Transactional(readOnly = true) public Result checkNoActiveExamReferences(final Long configurationNodeId) { - return Result.tryCatch(() -> !this.examConfigurationMapRecordMapper.selectByExample() + return Result.tryCatch(() -> this.examConfigurationMapRecordMapper.selectByExample() .where( ExamConfigurationMapRecordDynamicSqlSupport.configurationNodeId, isEqualTo(configurationNodeId)) @@ -396,11 +396,12 @@ public class ExamConfigurationMapDAOImpl implements ExamConfigurationMapDAO { private boolean isExamActive(final Long examId) { try { - return this.examRecordMapper.countByExample() + final boolean active = this.examRecordMapper.countByExample() .where(ExamRecordDynamicSqlSupport.id, isEqualTo(examId)) .and(ExamRecordDynamicSqlSupport.status, isIn(ACTIVE_EXAM_STATE_NAMES)) .build() .execute() >= 1; + return active; } catch (final Exception e) { log.warn("Failed to check exam status for exam: {}", examId, e); return false;