feat: Implement feature to acknowledge project time frames when assigning employees to projects (SCRUM-7 SCRUM-2) (!38)
Co-authored-by: Phan Huy Tran <p.tran@neusta.de> Reviewed-on: #38 Co-authored-by: Phan Huy Tran <ptran@noreply.localhost> Co-committed-by: Phan Huy Tran <ptran@noreply.localhost>
This commit is contained in:
parent
97e211946f
commit
5f6caa7fc2
16 changed files with 334 additions and 54 deletions
|
@ -1,5 +1,6 @@
|
|||
package de.szut.lf8_starter.project;
|
||||
|
||||
import de.szut.lf8_starter.project.dto.project.GetProjectDto;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -32,4 +33,18 @@ public class ProjectService {
|
|||
public void delete(Long id) {
|
||||
this.projectRepository.deleteById(id);
|
||||
}
|
||||
|
||||
public boolean isOverlapping(GetProjectDto getProjectDto, ProjectEntity existingProjectEntity) {
|
||||
return isDateRangeOverlapping(getProjectDto, existingProjectEntity) || isDateEqual(getProjectDto, existingProjectEntity);
|
||||
}
|
||||
|
||||
private boolean isDateRangeOverlapping(GetProjectDto getProjectDto, ProjectEntity existingProjectEntity) {
|
||||
return getProjectDto.getStartDate().isBefore(existingProjectEntity.getPlannedEndDate())
|
||||
&& getProjectDto.getPlannedEndDate().isAfter(existingProjectEntity.getStartDate());
|
||||
}
|
||||
|
||||
private boolean isDateEqual(GetProjectDto getProjectDto, ProjectEntity existingProjectEntity) {
|
||||
return getProjectDto.getStartDate().isEqual(existingProjectEntity.getStartDate())
|
||||
|| getProjectDto.getPlannedEndDate().isEqual(existingProjectEntity.getPlannedEndDate());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package de.szut.lf8_starter.project.action.crud;
|
||||
|
||||
import de.szut.lf8_starter.employee.EmployeeService;
|
||||
import de.szut.lf8_starter.project.ProjectEntity;
|
||||
import de.szut.lf8_starter.project.ProjectService;
|
||||
import de.szut.lf8_starter.project.dto.project.CreateProjectDto;
|
||||
|
@ -12,15 +13,18 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
|||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = "/projects")
|
||||
public class CreateProjectAction {
|
||||
private final EmployeeService employeeService;
|
||||
private final ProjectService projectService;
|
||||
private final ProjectMapper projectMapper;
|
||||
|
||||
public CreateProjectAction(ProjectService projectService, ProjectMapper mappingService) {
|
||||
public CreateProjectAction(EmployeeService employeeService, ProjectService projectService, ProjectMapper mappingService) {
|
||||
this.employeeService = employeeService;
|
||||
this.projectService = projectService;
|
||||
this.projectMapper = mappingService;
|
||||
}
|
||||
|
@ -29,14 +33,31 @@ public class CreateProjectAction {
|
|||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "201", description = "created project", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = GetProjectDto.class))}),
|
||||
@ApiResponse(responseCode = "400", description = "invalid JSON posted", content = @Content),
|
||||
@ApiResponse(responseCode = "401", description = "not authorized", content = @Content)})
|
||||
@ApiResponse(responseCode = "401", description = "not authorized", content = @Content),
|
||||
@ApiResponse(responseCode = "409", description = "Project dates conflict", content = @Content)
|
||||
})
|
||||
@PostMapping
|
||||
@ResponseStatus(code = HttpStatus.CREATED)
|
||||
public GetProjectDto create(@RequestBody @Valid CreateProjectDto createProjectDto) {
|
||||
ProjectEntity projectEntity = this.projectMapper.mapCreateDtoToEntity(createProjectDto);
|
||||
public ResponseEntity<Object> create(
|
||||
@RequestBody @Valid CreateProjectDto createProjectDto,
|
||||
@RequestHeader("Authorization") String accessToken
|
||||
) {
|
||||
ProjectEntity project = this.projectMapper.mapCreateDtoToEntity(createProjectDto);
|
||||
|
||||
projectEntity = this.projectService.create(projectEntity);
|
||||
for (Long employeeId : createProjectDto.getEmployees()) {
|
||||
if (!this.employeeService.employeeExists(accessToken, employeeId)) {
|
||||
return new ResponseEntity<>("Employee with ID: " + employeeId + " not found", HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
return this.projectMapper.mapToGetDto(projectEntity);
|
||||
for (GetProjectDto getProjectDto : this.employeeService.getProjects(employeeId)) {
|
||||
if (projectService.isOverlapping(getProjectDto, project)) {
|
||||
return new ResponseEntity<>("Project dates conflict with an existing project for Employee with ID: " + employeeId, HttpStatus.CONFLICT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.projectService.create(project);
|
||||
|
||||
return new ResponseEntity<>(this.projectMapper.mapToGetDto(project), HttpStatus.CREATED);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package de.szut.lf8_starter.project.action;
|
||||
package de.szut.lf8_starter.project.action.crud;
|
||||
|
||||
import de.szut.lf8_starter.project.ProjectEntity;
|
||||
import de.szut.lf8_starter.project.ProjectService;
|
|
@ -3,6 +3,7 @@ package de.szut.lf8_starter.project.action.employee;
|
|||
import de.szut.lf8_starter.employee.EmployeeService;
|
||||
import de.szut.lf8_starter.project.ProjectEntity;
|
||||
import de.szut.lf8_starter.project.ProjectService;
|
||||
import de.szut.lf8_starter.project.dto.project.GetProjectDto;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
|
@ -29,7 +30,8 @@ public class AddEmployeeToProjectAction {
|
|||
@Operation(summary = "Add an employee to a project")
|
||||
@ApiResponses(value = {
|
||||
@ApiResponse(responseCode = "204", description = "Employee added to project"),
|
||||
@ApiResponse(responseCode = "404", description = "Project or employee not found", content = @Content)
|
||||
@ApiResponse(responseCode = "404", description = "Project or employee not found", content = @Content),
|
||||
@ApiResponse(responseCode = "409", description = "Project dates conflict", content = @Content)
|
||||
})
|
||||
@PostMapping("/projects/{projectId}/employees/{employeeId}")
|
||||
public ResponseEntity<Object> create(
|
||||
|
@ -37,18 +39,26 @@ public class AddEmployeeToProjectAction {
|
|||
@PathVariable Long employeeId,
|
||||
@RequestHeader("Authorization") String accessToken
|
||||
) {
|
||||
Optional<ProjectEntity> project = this.projectService.findById(projectId);
|
||||
Optional<ProjectEntity> optionalProject = this.projectService.findById(projectId);
|
||||
|
||||
if (project.isEmpty()) {
|
||||
if (optionalProject.isEmpty()) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
ProjectEntity projectEntity = optionalProject.get();
|
||||
|
||||
if (!this.employeeService.employeeExists(accessToken, employeeId)) {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
project.get().getEmployees().add(employeeId);
|
||||
this.projectService.update(project.get());
|
||||
for (GetProjectDto getProjectDto : this.employeeService.getProjects(employeeId)) {
|
||||
if (this.projectService.isOverlapping(getProjectDto, projectEntity)) {
|
||||
return new ResponseEntity<>("Project dates conflict with an existing project for Employee with ID: " + employeeId, HttpStatus.CONFLICT);
|
||||
}
|
||||
}
|
||||
|
||||
projectEntity.getEmployees().add(employeeId);
|
||||
this.projectService.update(projectEntity);
|
||||
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
|
Reference in a new issue