From e011a5534e111050c6354bc9e63565d76d6d251b Mon Sep 17 00:00:00 2001 From: Pierre Tellier Date: Wed, 12 Mar 2025 10:21:08 +0100 Subject: [PATCH 1/4] feat: switched from String to ProjectDecisionValues --- .../java/enseirb/myinpulse/model/Project.java | 10 +++++----- .../myinpulse/model/ProjectDecisionValue.java | 8 ++++++++ .../repository/ProjectRepository.java | 2 +- .../myinpulse/service/AdminApiService.java | 20 +++++++++++-------- .../service/EntrepreneurApiService.java | 4 +++- .../service/database/ProjectService.java | 10 ++++++++-- 6 files changed, 37 insertions(+), 17 deletions(-) create mode 100644 MyINPulse-back/src/main/java/enseirb/myinpulse/model/ProjectDecisionValue.java diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/model/Project.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/model/Project.java index ac1c5df..b745c6f 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/model/Project.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/model/Project.java @@ -26,8 +26,7 @@ public class Project { private byte[] logo; private LocalDate creationDate; - @Column(length = 255) - private String projectStatus; + @Column private ProjectDecisionValue projectStatus; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "idAdministrator") @@ -42,11 +41,12 @@ public class Project { String projectName, byte[] logo, LocalDate creationDate, - String projectStatus, + ProjectDecisionValue projectStatus, Administrator projectAdministrator) { this.projectName = projectName; this.logo = logo; this.creationDate = creationDate; + // this.projectStatus = (long) projectStatus.ordinal(); this.projectStatus = projectStatus; this.projectAdministrator = projectAdministrator; } @@ -83,11 +83,11 @@ public class Project { this.creationDate = creationDate; } - public String getProjectStatus() { + public ProjectDecisionValue getProjectStatus() { return projectStatus; } - public void setProjectStatus(String projectStatus) { + public void setProjectStatus(ProjectDecisionValue projectStatus) { this.projectStatus = projectStatus; } diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/model/ProjectDecisionValue.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/model/ProjectDecisionValue.java new file mode 100644 index 0000000..ca38489 --- /dev/null +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/model/ProjectDecisionValue.java @@ -0,0 +1,8 @@ +package enseirb.myinpulse.model; + +public enum ProjectDecisionValue { + PENDING, + ACTIVE, + ENDED, + ABORTED +} diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/ProjectRepository.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/ProjectRepository.java index 2911655..0fc1b08 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/ProjectRepository.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/ProjectRepository.java @@ -10,5 +10,5 @@ import org.springframework.data.rest.core.annotation.RepositoryRestResource; public interface ProjectRepository extends JpaRepository { Iterable findByProjectAdministrator(Administrator administrator); - Iterable findByProjectStatus(String status); + Iterable findByProjectStatus(Long status); } diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/AdminApiService.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/AdminApiService.java index 400c2b6..974754d 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/AdminApiService.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/AdminApiService.java @@ -1,5 +1,7 @@ package enseirb.myinpulse.service; +import static enseirb.myinpulse.model.ProjectDecisionValue.ACTIVE; + import enseirb.myinpulse.model.*; import enseirb.myinpulse.service.database.AdministratorService; import enseirb.myinpulse.service.database.ProjectService; @@ -27,7 +29,7 @@ public class AdminApiService { this.administratorService = administratorService; } - // TODO: test + // TODO: check if test are sufficient public Iterable getProjectsOfAdmin(String email) { return projectService.getProjectsByAdminId( administratorService.getAdministratorById( @@ -46,13 +48,15 @@ public class AdminApiService { // TODO: test public void validateProject(ProjectDecision decision) { - projectService.updateProject( - decision.projectId, - null, - null, - null, - "ACTIVE", - this.administratorService.getAdministratorById(decision.projectId)); + if (decision.isAccepted == 1) { + projectService.updateProject( + decision.projectId, + null, + null, + null, + ACTIVE, + this.administratorService.getAdministratorById(decision.projectId)); + } } // TODO: solve todo + test diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/EntrepreneurApiService.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/EntrepreneurApiService.java index 61b16ab..f1d6260 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/EntrepreneurApiService.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/EntrepreneurApiService.java @@ -1,5 +1,7 @@ package enseirb.myinpulse.service; +import static enseirb.myinpulse.model.ProjectDecisionValue.PENDING; + import enseirb.myinpulse.model.Project; import enseirb.myinpulse.model.SectionCell; import enseirb.myinpulse.service.database.ProjectService; @@ -114,7 +116,7 @@ public class EntrepreneurApiService { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Le projet fourni est vide"); } logger.info("User {} created a new project with id {}", mail, project.getIdProject()); - project.setProjectStatus("PENDING"); + project.setProjectStatus(PENDING); projectService.addNewProject(project); } } diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/ProjectService.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/ProjectService.java index 10dc7e9..d851a43 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/ProjectService.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/ProjectService.java @@ -1,7 +1,10 @@ package enseirb.myinpulse.service.database; +import static enseirb.myinpulse.model.ProjectDecisionValue.PENDING; + import enseirb.myinpulse.model.Administrator; import enseirb.myinpulse.model.Project; +import enseirb.myinpulse.model.ProjectDecisionValue; import enseirb.myinpulse.repository.ProjectRepository; import org.apache.logging.log4j.LogManager; @@ -54,7 +57,7 @@ public class ProjectService { String projectName, byte[] logo, LocalDate creationDate, - String projectStatus, + ProjectDecisionValue projectStatus, Administrator administrator) { Optional project = this.projectRepository.findById(id); @@ -76,11 +79,14 @@ public class ProjectService { } if (projectStatus != null) { + // TODO: check if this is really useful + /* if (!validateStatus(projectStatus)) { logger.error("updateProjectStatus: Invalid status {}", projectStatus); throw new ResponseStatusException( HttpStatus.NOT_ACCEPTABLE, "Ce status n'est pas accepté"); } + */ project.get().setProjectStatus(projectStatus); } @@ -96,7 +102,7 @@ public class ProjectService { } public Iterable getPendingProjects() { - return this.projectRepository.findByProjectStatus("PENDING"); + return this.projectRepository.findByProjectStatus((long) PENDING.ordinal()); } public void deleteProjectById(Long id) { From 419ceec1bc93326236cd34a802878cd8a431ee15 Mon Sep 17 00:00:00 2001 From: Pierre Tellier Date: Wed, 12 Mar 2025 10:25:19 +0100 Subject: [PATCH 2/4] feat: switched from String to ProjectDecisionValues --- .../java/enseirb/myinpulse/repository/ProjectRepository.java | 3 ++- .../main/java/enseirb/myinpulse/service/AdminApiService.java | 4 +++- .../enseirb/myinpulse/service/database/ProjectService.java | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/ProjectRepository.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/ProjectRepository.java index 0fc1b08..8f452f6 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/ProjectRepository.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/ProjectRepository.java @@ -2,6 +2,7 @@ package enseirb.myinpulse.repository; import enseirb.myinpulse.model.Administrator; import enseirb.myinpulse.model.Project; +import enseirb.myinpulse.model.ProjectDecisionValue; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; @@ -10,5 +11,5 @@ import org.springframework.data.rest.core.annotation.RepositoryRestResource; public interface ProjectRepository extends JpaRepository { Iterable findByProjectAdministrator(Administrator administrator); - Iterable findByProjectStatus(Long status); + Iterable findByProjectStatus(ProjectDecisionValue status); } diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/AdminApiService.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/AdminApiService.java index 974754d..d268d98 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/AdminApiService.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/AdminApiService.java @@ -61,7 +61,9 @@ public class AdminApiService { // TODO: solve todo + test public void addNewProject(Project project) { - projectService.addNewProject(project); // TODO: how can the front know the ID ? + projectService.addNewProject( + project); // TODO: how can the front know the ID ? => it does not, thus needing to + // have null in the project id field } // TODO diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/ProjectService.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/ProjectService.java index d851a43..5c32ae2 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/ProjectService.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/ProjectService.java @@ -102,7 +102,7 @@ public class ProjectService { } public Iterable getPendingProjects() { - return this.projectRepository.findByProjectStatus((long) PENDING.ordinal()); + return this.projectRepository.findByProjectStatus(PENDING); } public void deleteProjectById(Long id) { From 64da3c9ab00b4dfcaaf4eaf347a887804aed292c Mon Sep 17 00:00:00 2001 From: Pierre Tellier Date: Wed, 12 Mar 2025 12:07:48 +0100 Subject: [PATCH 3/4] feat: tests on AdminApiService --- .../myinpulse/AdminApiServiceTest.java | 117 +++++++++++++++--- 1 file changed, 102 insertions(+), 15 deletions(-) diff --git a/MyINPulse-back/src/test/java/enseirb/myinpulse/AdminApiServiceTest.java b/MyINPulse-back/src/test/java/enseirb/myinpulse/AdminApiServiceTest.java index 47f8af4..abd21fb 100644 --- a/MyINPulse-back/src/test/java/enseirb/myinpulse/AdminApiServiceTest.java +++ b/MyINPulse-back/src/test/java/enseirb/myinpulse/AdminApiServiceTest.java @@ -1,10 +1,12 @@ package enseirb.myinpulse; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static enseirb.myinpulse.model.ProjectDecisionValue.*; + +import static org.junit.jupiter.api.Assertions.*; import enseirb.myinpulse.model.Administrator; import enseirb.myinpulse.model.Project; +import enseirb.myinpulse.model.ProjectDecision; import enseirb.myinpulse.service.AdminApiService; import enseirb.myinpulse.service.database.AdministratorService; import enseirb.myinpulse.service.database.ProjectService; @@ -23,7 +25,9 @@ import java.util.List; @SpringBootTest @Transactional public class AdminApiServiceTest { + private static long administratorid; @Autowired private AdminApiService adminApiService; + @Autowired private ProjectService projectService; @BeforeAll static void setup( @@ -36,30 +40,36 @@ public class AdminApiServiceTest { "testAdminEmpty@example.com", "testAdmin@example.com", "")); - administratorService.addAdministrator( - new Administrator( - "admin2", - "admin2", - "testAdminFull@example.com", - "testAdmin@example.com", - "")); + Administrator a = + administratorService.addAdministrator( + new Administrator( + "admin2", + "admin2", + "testAdminFull@example.com", + "testAdmin@example.com", + "")); + administratorid = a.getIdUser(); projectService.addNewProject( new Project( "sampleProjectAdminApiService", null, LocalDate.now(), - "ONGOING", + ACTIVE, administratorService.getAdministratorByPrimaryMain( "testAdminFull@example.com"))); } + private List IterableToList(Iterable iterable) { + List l = new ArrayList<>(); + iterable.forEach(l::add); + return l; + } + @Test void getProjectOfAdminIsEmpty() { Iterable projects = adminApiService.getProjectsOfAdmin("testAdminEmpty@example.com"); - List l = new ArrayList<>(); - projects.forEach(l::add); - assertEquals(0, l.size()); + assertEquals(0, IterableToList(projects).size()); } @Test @@ -77,10 +87,87 @@ public class AdminApiServiceTest { void getProjectOfAdminNotEmpty() { Iterable projects = adminApiService.getProjectsOfAdmin("testAdminFull@example.com"); - List l = new ArrayList<>(); - projects.forEach(l::add); + List l = IterableToList(projects); assertEquals(1, l.size()); Project p = l.getFirst(); assertEquals(p.getProjectName(), "sampleProjectAdminApiService"); } + + @Test + void getPendingProjectsEmpty() { + assertEquals(0, IterableToList(this.adminApiService.getPendingProjects()).size()); + } + + @Test + void getPendingProjectsNotEmpty() { + this.projectService.addNewProject( + new Project( + "PendingProjectAdminApiService1", null, LocalDate.now(), PENDING, null)); + this.projectService.addNewProject( + new Project( + "PendingProjectAdminApiService2", null, LocalDate.now(), PENDING, null)); + Iterable pendingProjects = this.adminApiService.getPendingProjects(); + List pendingProjectsList = IterableToList(pendingProjects); + assertEquals(2, pendingProjectsList.size()); + assertTrue( + List.of("PendingProjectAdminApiService1", "PendingProjectAdminApiService2") + .contains(pendingProjectsList.getFirst().getProjectName())); + assertTrue( + List.of("PendingProjectAdminApiService1", "PendingProjectAdminApiService2") + .contains(pendingProjectsList.getLast().getProjectName())); + } + + @Test + void validateInexistantProject() { + ProjectDecision d = new ProjectDecision(-1, 0, 1); + assertThrows(ResponseStatusException.class, () -> this.adminApiService.validateProject(d)); + } + + @Test + void validateExistantProject() { + Project p = + new Project("PendingProjectAdminApiService2", null, LocalDate.now(), PENDING, null); + this.projectService.addNewProject(p); + assertEquals(PENDING, p.getProjectStatus()); + ProjectDecision d = new ProjectDecision(p.getIdProject(), administratorid, 1); + this.adminApiService.validateProject(d); + assertEquals(ACTIVE, p.getProjectStatus()); + + // Check if the project was really updated in the database + assertEquals(0, IterableToList(this.adminApiService.getPendingProjects()).size()); + } + + @Test + void refuseExistantProject() { + Project p = + new Project("PendingProjectAdminApiService2", null, LocalDate.now(), PENDING, null); + this.projectService.addNewProject(p); + assertEquals(PENDING, p.getProjectStatus()); + ProjectDecision d = new ProjectDecision(p.getIdProject(), administratorid, 0); + this.adminApiService.validateProject(d); + assertEquals(REJECTED, p.getProjectStatus()); + + // Check if the project was really updated in the database + assertEquals(0, IterableToList(this.adminApiService.getPendingProjects()).size()); + } + + @Test + void addProject() { + assertEquals(0, IterableToList(this.adminApiService.getPendingProjects()).size()); + Project p1 = + new Project("PendingProjectAdminApiService2", null, LocalDate.now(), PENDING, null); + this.adminApiService.addNewProject(p1); + + assertEquals(1, IterableToList(this.adminApiService.getPendingProjects()).size()); + } + + @Test + void addDuplicateProject() { + Project p1 = + new Project("PendingProjectAdminApiService2", null, LocalDate.now(), PENDING, null); + Project p2 = + new Project("PendingProjectAdminApiService2", null, LocalDate.now(), PENDING, null); + this.adminApiService.addNewProject(p1); + assertThrows(ResponseStatusException.class, () -> this.adminApiService.addNewProject(p2)); + } } From 653f9236937769c93e6ba96ca0330ced98ab5651 Mon Sep 17 00:00:00 2001 From: Pierre Tellier Date: Wed, 12 Mar 2025 12:08:49 +0100 Subject: [PATCH 4/4] fix: bugfix --- .../myinpulse/model/ProjectDecision.java | 18 +++++++++ .../myinpulse/model/ProjectDecisionValue.java | 3 +- .../repository/ProjectRepository.java | 4 ++ .../myinpulse/service/AdminApiService.java | 39 +++++++++++-------- .../service/database/ProjectService.java | 13 +++++++ 5 files changed, 60 insertions(+), 17 deletions(-) diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/model/ProjectDecision.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/model/ProjectDecision.java index a2d3575..22eec2d 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/model/ProjectDecision.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/model/ProjectDecision.java @@ -4,4 +4,22 @@ public class ProjectDecision { public long projectId; public long adminId; public long isAccepted; + + public ProjectDecision(long projectId, long adminId, long isAccepted) { + this.projectId = projectId; + this.adminId = adminId; + this.isAccepted = isAccepted; + } + + @Override + public String toString() { + return "ProjectDecision{" + + "projectId=" + + projectId + + ", adminId=" + + adminId + + ", isAccepted=" + + isAccepted + + '}'; + } } diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/model/ProjectDecisionValue.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/model/ProjectDecisionValue.java index ca38489..a47c5f9 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/model/ProjectDecisionValue.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/model/ProjectDecisionValue.java @@ -4,5 +4,6 @@ public enum ProjectDecisionValue { PENDING, ACTIVE, ENDED, - ABORTED + ABORTED, + REJECTED, } diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/ProjectRepository.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/ProjectRepository.java index 8f452f6..7cf5214 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/ProjectRepository.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/repository/ProjectRepository.java @@ -7,9 +7,13 @@ import enseirb.myinpulse.model.ProjectDecisionValue; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.rest.core.annotation.RepositoryRestResource; +import java.util.Optional; + @RepositoryRestResource public interface ProjectRepository extends JpaRepository { Iterable findByProjectAdministrator(Administrator administrator); Iterable findByProjectStatus(ProjectDecisionValue status); + + Optional findByProjectName(String projectName); } diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/AdminApiService.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/AdminApiService.java index d268d98..17059b9 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/AdminApiService.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/AdminApiService.java @@ -1,6 +1,7 @@ package enseirb.myinpulse.service; import static enseirb.myinpulse.model.ProjectDecisionValue.ACTIVE; +import static enseirb.myinpulse.model.ProjectDecisionValue.REJECTED; import enseirb.myinpulse.model.*; import enseirb.myinpulse.service.database.AdministratorService; @@ -29,7 +30,7 @@ public class AdminApiService { this.administratorService = administratorService; } - // TODO: check if test are sufficient + // TODO: check if tests are sufficients - peer verification required public Iterable getProjectsOfAdmin(String email) { return projectService.getProjectsByAdminId( administratorService.getAdministratorById( @@ -41,29 +42,35 @@ public class AdminApiService { throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, "Not implemented yet"); } - // TODO: test + // TODO: check if tests are sufficient - peer verification required public Iterable getPendingProjects() { return this.projectService.getPendingProjects(); } - // TODO: test + // TODO: check if tests are sufficient - peer verification required public void validateProject(ProjectDecision decision) { - if (decision.isAccepted == 1) { - projectService.updateProject( - decision.projectId, - null, - null, - null, - ACTIVE, - this.administratorService.getAdministratorById(decision.projectId)); - } + projectService.updateProject( + decision.projectId, + null, + null, + null, + (decision.isAccepted == 1) ? ACTIVE : REJECTED, + this.administratorService.getAdministratorById(decision.adminId)); } - // TODO: solve todo + test + // TODO: check if tests are sufficient - peer verification required public void addNewProject(Project project) { - projectService.addNewProject( - project); // TODO: how can the front know the ID ? => it does not, thus needing to - // have null in the project id field + project.setIdProject(null); + // We remove it from the request to be sure that it will be auto generated + try { + this.projectService.getProjectByName(project.getProjectName(), true); + throw new ResponseStatusException(HttpStatus.CONFLICT, "Project already exists"); + } catch (ResponseStatusException e) { + if (e.getStatusCode() == HttpStatus.CONFLICT) { + throw new ResponseStatusException(HttpStatus.CONFLICT, "Project already exists"); + } + projectService.addNewProject(project); + } } // TODO diff --git a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/ProjectService.java b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/ProjectService.java index 5c32ae2..32fc4c4 100644 --- a/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/ProjectService.java +++ b/MyINPulse-back/src/main/java/enseirb/myinpulse/service/database/ProjectService.java @@ -108,4 +108,17 @@ public class ProjectService { public void deleteProjectById(Long id) { this.projectRepository.deleteById(id); } + + public Project getProjectByName(String name, boolean noerror) { + Optional project = this.projectRepository.findByProjectName(name); + if (project.isEmpty()) { + if (noerror) logger.error("No project found with name {}", name); + throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Ce projet n'existe pas"); + } + return project.get(); + } + + public Project getProjectByName(String name) { + return getProjectByName(name, false); + } }