diff --git a/src/main/java/de/hmmh/pmt/ApiController.java b/src/main/java/de/hmmh/pmt/ApiController.java index 6c57d91..19d7356 100644 --- a/src/main/java/de/hmmh/pmt/ApiController.java +++ b/src/main/java/de/hmmh/pmt/ApiController.java @@ -9,6 +9,7 @@ import de.hmmh.pmt.employee.api.EmployeeControllerApi; 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; @@ -30,6 +31,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; @@ -87,7 +92,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); @@ -121,16 +126,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 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); } diff --git a/src/main/java/de/hmmh/pmt/db/Project.java b/src/main/java/de/hmmh/pmt/db/Project.java index 0a70189..2f973e6 100644 --- a/src/main/java/de/hmmh/pmt/db/Project.java +++ b/src/main/java/de/hmmh/pmt/db/Project.java @@ -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> violations = validator.validate(this); - - return violations.isEmpty() && - plannedEnd.isAfter(start) && - (realEnd == null || realEnd.isAfter(start)); - } - } - diff --git a/src/main/java/de/hmmh/pmt/util/Validator.java b/src/main/java/de/hmmh/pmt/util/Validator.java new file mode 100644 index 0000000..f496d56 --- /dev/null +++ b/src/main/java/de/hmmh/pmt/util/Validator.java @@ -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> 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 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); + }); + } + +}