diff --git a/src/main/java/com/rte_france/antares/datamanager_back/controller/ProjectController.java b/src/main/java/com/rte_france/antares/datamanager_back/controller/ProjectController.java index e13c358..ab78cb8 100644 --- a/src/main/java/com/rte_france/antares/datamanager_back/controller/ProjectController.java +++ b/src/main/java/com/rte_france/antares/datamanager_back/controller/ProjectController.java @@ -63,4 +63,9 @@ public ResponseEntity findProjectById(@PathVariable Integer id) { return new ResponseEntity<>(toProjectDto(projectService.findProjectById(id)), HttpStatus.OK); } + @Operation(summary = "Delete project if it contains no studies") + @DeleteMapping("/{id}") + public void deleteProject(@PathVariable Integer id) { + projectService.deleteProjectById(id); + } } diff --git a/src/main/java/com/rte_france/antares/datamanager_back/repository/model/ProjectEntity.java b/src/main/java/com/rte_france/antares/datamanager_back/repository/model/ProjectEntity.java index f80d058..480f48b 100644 --- a/src/main/java/com/rte_france/antares/datamanager_back/repository/model/ProjectEntity.java +++ b/src/main/java/com/rte_france/antares/datamanager_back/repository/model/ProjectEntity.java @@ -5,7 +5,9 @@ import lombok.*; import java.time.LocalDateTime; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; @Getter @Setter @@ -42,4 +44,8 @@ public class ProjectEntity { @CollectionTable(name = "project_tags", joinColumns = @JoinColumn(name = "project_id")) @Column(name = "tag") private List tags; + + @OneToMany(mappedBy = "project", cascade = CascadeType.ALL, orphanRemoval = true) + private Set pinnedProjectEntities = new LinkedHashSet<>(); + } \ No newline at end of file diff --git a/src/main/java/com/rte_france/antares/datamanager_back/service/ProjectService.java b/src/main/java/com/rte_france/antares/datamanager_back/service/ProjectService.java index 19f3c54..7623eba 100644 --- a/src/main/java/com/rte_france/antares/datamanager_back/service/ProjectService.java +++ b/src/main/java/com/rte_france/antares/datamanager_back/service/ProjectService.java @@ -18,6 +18,8 @@ public interface ProjectService { ProjectEntity pinProjectForUser(String userId, Integer projectId); + void deleteProjectById(Integer projectId); + } diff --git a/src/main/java/com/rte_france/antares/datamanager_back/service/impl/ProjectServiceImpl.java b/src/main/java/com/rte_france/antares/datamanager_back/service/impl/ProjectServiceImpl.java index 45210d1..8cf3879 100644 --- a/src/main/java/com/rte_france/antares/datamanager_back/service/impl/ProjectServiceImpl.java +++ b/src/main/java/com/rte_france/antares/datamanager_back/service/impl/ProjectServiceImpl.java @@ -147,6 +147,16 @@ public ProjectEntity pinProjectForUser(String userId, Integer projectId) { return project; } + @Override + public void deleteProjectById(Integer projectId) { + ProjectEntity project = projectRepository.findById(projectId) + .orElseThrow(() -> new ResourceNotFoundException("Project not found with ID: " + projectId)); + if (project.getStudies() != null && !project.getStudies().isEmpty()) { + throw new BadRequestException("Project contains studies and cannot be deleted"); + } + projectRepository.deleteById(projectId); + } + private void checkIfUserHasALreadyMaxPinnedProjects(String userId) { List pinnedProjects = pinnedProjectRepository.findById_Nni(userId); if (pinnedProjects.size() >= 3) { diff --git a/src/test/java/com/rte_france/antares/datamanager_back/controller/ProjectControllerTest.java b/src/test/java/com/rte_france/antares/datamanager_back/controller/ProjectControllerTest.java index 273b909..59fd65e 100644 --- a/src/test/java/com/rte_france/antares/datamanager_back/controller/ProjectControllerTest.java +++ b/src/test/java/com/rte_france/antares/datamanager_back/controller/ProjectControllerTest.java @@ -2,6 +2,7 @@ import com.rte_france.antares.datamanager_back.dto.ProjectDto; import com.rte_france.antares.datamanager_back.exception.BadRequestException; +import com.rte_france.antares.datamanager_back.exception.ResourceNotFoundException; import com.rte_france.antares.datamanager_back.repository.model.ProjectEntity; import com.rte_france.antares.datamanager_back.service.ProjectService; import org.junit.jupiter.api.BeforeEach; @@ -155,5 +156,36 @@ void findProjectById_returnsProjectDtoWhenProjectExists() throws Exception { .andExpect(jsonPath("$.name").value("name2050")) .andExpect(jsonPath("$.description").value("project2050")); } +@Test +void deleteProject_returnsNoContentWhenProjectDeleted() throws Exception { + Integer projectId = 1; + doNothing().when(projectService).deleteProjectById(projectId); + + mockMvc.perform(delete("/v1/project/{id}", projectId) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); +} + +@Test +void deleteProject_returnsNotFoundWhenProjectDoesNotExist() throws Exception { + Integer projectId = 1; + + doThrow(new ResourceNotFoundException("Project not found")).when(projectService).deleteProjectById(projectId); + + mockMvc.perform(delete("/v1/project/{id}", projectId) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNotFound()); +} + +@Test +void deleteProject_returnsBadRequestWhenProjectContainsStudies() throws Exception { + Integer projectId = 1; + + doThrow(new BadRequestException("Project contains studies and cannot be deleted")).when(projectService).deleteProjectById(projectId); + + mockMvc.perform(delete("/v1/project/{id}", projectId) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isInternalServerError()); +} } \ No newline at end of file diff --git a/src/test/java/com/rte_france/antares/datamanager_back/service/ProjectServiceImplTest.java b/src/test/java/com/rte_france/antares/datamanager_back/service/ProjectServiceImplTest.java index dec2326..d593466 100644 --- a/src/test/java/com/rte_france/antares/datamanager_back/service/ProjectServiceImplTest.java +++ b/src/test/java/com/rte_france/antares/datamanager_back/service/ProjectServiceImplTest.java @@ -213,4 +213,50 @@ void pinProjectForUser_throwsExceptionWhenUserHasMaxPinnedProjects() { assertEquals("You have already 3 pinned projects , please unpin one before pinning another one.", exception.getMessage()); verify(pinnedProjectRepository, never()).save(any(PinnedProjectEntity.class)); } + + @Test +void deleteProjectById_deletesProjectWhenNoStudies() { + Integer projectId = 1; + ProjectEntity project = new ProjectEntity(); + project.setId(projectId); + + when(projectRepository.findById(projectId)).thenReturn(Optional.of(project)); + + projectService.deleteProjectById(projectId); + + verify(projectRepository, times(1)).deleteById(projectId); +} + +@Test +void deleteProjectById_throwsExceptionWhenProjectNotFound() { + Integer projectId = 1; + + when(projectRepository.findById(projectId)).thenReturn(Optional.empty()); + + ResourceNotFoundException exception = assertThrows( + ResourceNotFoundException.class, + () -> projectService.deleteProjectById(projectId) + ); + + assertEquals("Project not found with ID: 1", exception.getMessage()); + verify(projectRepository, never()).deleteById(projectId); +} + +@Test +void deleteProjectById_throwsExceptionWhenProjectContainsStudies() { + Integer projectId = 1; + ProjectEntity project = new ProjectEntity(); + project.setId(projectId); + project.setStudies(List.of(new StudyEntity())); + + when(projectRepository.findById(projectId)).thenReturn(Optional.of(project)); + + BadRequestException exception = assertThrows( + BadRequestException.class, + () -> projectService.deleteProjectById(projectId) + ); + + assertEquals("Project contains studies and cannot be deleted", exception.getMessage()); + verify(projectRepository, never()).deleteById(projectId); +} }