PMT-43: Separate Validation Logic

This commit is contained in:
Dominik Säume 2024-10-23 09:48:18 +02:00
parent 516a088817
commit 21040c69b6
3 changed files with 59 additions and 23 deletions

View file

@ -10,6 +10,7 @@ import de.hmmh.pmt.employee.ApiClientFactory;
import de.hmmh.pmt.employee.dtos.EmployeeResponseDTO;
import de.hmmh.pmt.oas.DefaultApi;
import de.hmmh.pmt.util.Mapper;
import de.hmmh.pmt.util.Validator;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
@ -31,6 +32,10 @@ public class ApiController implements DefaultApi {
@Autowired
private ApiClientFactory apiClientFactory;
@Autowired
private Validator validator;
@Autowired
private ApiTools apiTools;
@Autowired
private ProjectRepository projectRepository;
@Autowired
AllocationRepository allocationRepository;
@ -88,7 +93,7 @@ public class ApiController implements DefaultApi {
}
Project project = mapper.map(body);
if (!project.isValid()) {
if (!validator.isValidProject(project)) {
return new ResponseEntity<>(HttpStatus.UNPROCESSABLE_ENTITY);
}
projectRepository.save(project);
@ -122,16 +127,11 @@ public class ApiController implements DefaultApi {
return new ResponseEntity<>(HttpStatus.UNPROCESSABLE_ENTITY);
}
long start = project.getStart().toEpochSecond(ZoneOffset.UTC);
long plannedEnd = project.getPlannedEnd().toEpochSecond(ZoneOffset.UTC);
List<Allocation> allocations = allocationRepository.findAllByEmployeeId(body.getEmployeeId());
if (allocations.stream()
.map(Allocation::getProject)
.anyMatch(allocatedProject -> {
long allocatedStart = allocatedProject.getStart().toEpochSecond(ZoneOffset.UTC);
long allocatedPlannedEnd = allocatedProject.getPlannedEnd().toEpochSecond(ZoneOffset.UTC);
return Math.max(start, allocatedStart) <= Math.min(plannedEnd, allocatedPlannedEnd);
})) {
if (validator.areAllocationTimeRangesOverlapping(
project.getStart(),
project.getPlannedEnd(),
allocationRepository.findAllByEmployeeId(body.getEmployeeId())
)) {
return new ResponseEntity<>(HttpStatus.UNPROCESSABLE_ENTITY);
}

View file

@ -47,16 +47,4 @@ public class Project {
private LocalDateTime plannedEnd;
private LocalDateTime realEnd; // Cant be named just "end" because it's and SQL Keyword
public boolean isValid() {
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
Set<ConstraintViolation<Project>> violations = validator.validate(this);
return violations.isEmpty() &&
plannedEnd.isAfter(start) &&
(realEnd == null || realEnd.isAfter(start));
}
}

View file

@ -0,0 +1,48 @@
package de.hmmh.pmt.util;
import de.hmmh.pmt.db.Allocation;
import de.hmmh.pmt.db.Project;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Set;
@Component
public class Validator {
public boolean isValidProject(Project project) {
jakarta.validation.Validator validator = Validation
.buildDefaultValidatorFactory()
.getValidator();
Set<ConstraintViolation<Project>> violations = validator.validate(project);
LocalDateTime start = project.getStart();
LocalDateTime plannedEnd = project.getPlannedEnd();
LocalDateTime realEnd = project.getRealEnd();
return violations.isEmpty() &&
plannedEnd.isAfter(start) &&
(realEnd == null || realEnd.isAfter(start));
}
public boolean areAllocationTimeRangesOverlapping(
LocalDateTime start,
LocalDateTime plannedEnd,
List<Allocation> allocations
){
long startUnix = start.toEpochSecond(ZoneOffset.UTC);
long plannedEndUnix = plannedEnd.toEpochSecond(ZoneOffset.UTC);
return allocations.stream()
.map(Allocation::getProject)
.anyMatch(allocatedProject -> {
long allocatedStart = allocatedProject.getStart().toEpochSecond(ZoneOffset.UTC);
long allocatedPlannedEnd = allocatedProject.getPlannedEnd().toEpochSecond(ZoneOffset.UTC);
return Math.max(startUnix, allocatedStart) <= Math.min(plannedEndUnix, allocatedPlannedEnd);
});
}
}