backend-api #6

Merged
piair merged 107 commits from backend-api into main 2025-03-26 19:04:09 +01:00
8 changed files with 185 additions and 31 deletions
Showing only changes of commit 307c7e700b - Show all commits

View File

@ -26,8 +26,7 @@ public class Project {
private byte[] logo; private byte[] logo;
private LocalDate creationDate; private LocalDate creationDate;
@Column(length = 255) @Column private ProjectDecisionValue projectStatus;
private String projectStatus;
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "idAdministrator") @JoinColumn(name = "idAdministrator")
@ -42,11 +41,12 @@ public class Project {
String projectName, String projectName,
byte[] logo, byte[] logo,
LocalDate creationDate, LocalDate creationDate,
String projectStatus, ProjectDecisionValue projectStatus,
Administrator projectAdministrator) { Administrator projectAdministrator) {
this.projectName = projectName; this.projectName = projectName;
this.logo = logo; this.logo = logo;
this.creationDate = creationDate; this.creationDate = creationDate;
// this.projectStatus = (long) projectStatus.ordinal();
this.projectStatus = projectStatus; this.projectStatus = projectStatus;
this.projectAdministrator = projectAdministrator; this.projectAdministrator = projectAdministrator;
} }
@ -83,11 +83,11 @@ public class Project {
this.creationDate = creationDate; this.creationDate = creationDate;
} }
public String getProjectStatus() { public ProjectDecisionValue getProjectStatus() {
return projectStatus; return projectStatus;
} }
public void setProjectStatus(String projectStatus) { public void setProjectStatus(ProjectDecisionValue projectStatus) {
this.projectStatus = projectStatus; this.projectStatus = projectStatus;
} }

View File

@ -4,4 +4,22 @@ public class ProjectDecision {
public long projectId; public long projectId;
public long adminId; public long adminId;
public long isAccepted; 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
+ '}';
}
} }

View File

@ -0,0 +1,9 @@
package enseirb.myinpulse.model;
public enum ProjectDecisionValue {
PENDING,
ACTIVE,
ENDED,
ABORTED,
REJECTED,
}

View File

@ -2,13 +2,18 @@ package enseirb.myinpulse.repository;
import enseirb.myinpulse.model.Administrator; import enseirb.myinpulse.model.Administrator;
import enseirb.myinpulse.model.Project; import enseirb.myinpulse.model.Project;
import enseirb.myinpulse.model.ProjectDecisionValue;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource; import org.springframework.data.rest.core.annotation.RepositoryRestResource;
import java.util.Optional;
@RepositoryRestResource @RepositoryRestResource
public interface ProjectRepository extends JpaRepository<Project, Long> { public interface ProjectRepository extends JpaRepository<Project, Long> {
Iterable<Project> findByProjectAdministrator(Administrator administrator); Iterable<Project> findByProjectAdministrator(Administrator administrator);
Iterable<Project> findByProjectStatus(String status); Iterable<Project> findByProjectStatus(ProjectDecisionValue status);
Optional<Project> findByProjectName(String projectName);
} }

View File

@ -1,5 +1,8 @@
package enseirb.myinpulse.service; 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.model.*;
import enseirb.myinpulse.service.database.AdministratorService; import enseirb.myinpulse.service.database.AdministratorService;
import enseirb.myinpulse.service.database.ProjectService; import enseirb.myinpulse.service.database.ProjectService;
@ -44,7 +47,7 @@ public class AdminApiService {
this.reportService = reportService; this.reportService = reportService;
} }
// TODO: test // TODO: check if tests are sufficients - peer verification required
public Iterable<Project> getProjectsOfAdmin(String mail) { public Iterable<Project> getProjectsOfAdmin(String mail) {
return projectService.getProjectsByAdminId( return projectService.getProjectsByAdminId(
administratorService.getAdministratorById( administratorService.getAdministratorById(
@ -54,27 +57,38 @@ public class AdminApiService {
// TODO // TODO
public Iterable<Appointment> getUpcomingAppointments(String mail) { public Iterable<Appointment> getUpcomingAppointments(String mail) {
logger.info("User {} check their upcoming appointments", mail); logger.info("User {} check their upcoming appointments", mail);
throw new ResponseStatusException(HttpStatus.NOT_IMPLEMENTED, "Not implemented yet");
} }
// TODO: test // TODO: check if tests are sufficient - peer verification required
public Iterable<Project> getPendingProjects() { public Iterable<Project> getPendingProjects() {
return this.projectService.getPendingProjects(); return this.projectService.getPendingProjects();
} }
// TODO: test // TODO: check if tests are sufficient - peer verification required
public void validateProject(ProjectDecision decision) { public void validateProject(ProjectDecision decision) {
projectService.updateProject( projectService.updateProject(
decision.projectId, decision.projectId,
null, null,
null, null,
null, null,
"ACTIVE", (decision.isAccepted == 1) ? ACTIVE : REJECTED,
this.administratorService.getAdministratorById(decision.projectId)); this.administratorService.getAdministratorById(decision.adminId));
} }
// TODO: solve todo + test // TODO: check if tests are sufficient - peer verification required
public void addNewProject(Project project) { public void addNewProject(Project project) {
projectService.addNewProject(project); // TODO: how can the front know the ID ? 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);
}
} }
public void createAppointmentReport(long appointmentId, Report report, String mail) { public void createAppointmentReport(long appointmentId, Report report, String mail) {

View File

@ -1,5 +1,7 @@
package enseirb.myinpulse.service; package enseirb.myinpulse.service;
import static enseirb.myinpulse.model.ProjectDecisionValue.PENDING;
import enseirb.myinpulse.model.Project; import enseirb.myinpulse.model.Project;
import enseirb.myinpulse.model.SectionCell; import enseirb.myinpulse.model.SectionCell;
import enseirb.myinpulse.service.database.ProjectService; import enseirb.myinpulse.service.database.ProjectService;
@ -114,7 +116,7 @@ public class EntrepreneurApiService {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Le projet fourni est vide"); throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Le projet fourni est vide");
} }
logger.info("User {} created a new project with id {}", mail, project.getIdProject()); logger.info("User {} created a new project with id {}", mail, project.getIdProject());
project.setProjectStatus("PENDING"); project.setProjectStatus(PENDING);
projectService.addNewProject(project); projectService.addNewProject(project);
} }
} }

View File

@ -1,7 +1,10 @@
package enseirb.myinpulse.service.database; package enseirb.myinpulse.service.database;
import static enseirb.myinpulse.model.ProjectDecisionValue.PENDING;
import enseirb.myinpulse.model.Administrator; import enseirb.myinpulse.model.Administrator;
import enseirb.myinpulse.model.Project; import enseirb.myinpulse.model.Project;
import enseirb.myinpulse.model.ProjectDecisionValue;
import enseirb.myinpulse.repository.ProjectRepository; import enseirb.myinpulse.repository.ProjectRepository;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
@ -54,7 +57,7 @@ public class ProjectService {
String projectName, String projectName,
byte[] logo, byte[] logo,
LocalDate creationDate, LocalDate creationDate,
String projectStatus, ProjectDecisionValue projectStatus,
Administrator administrator) { Administrator administrator) {
Optional<Project> project = this.projectRepository.findById(id); Optional<Project> project = this.projectRepository.findById(id);
@ -76,11 +79,14 @@ public class ProjectService {
} }
if (projectStatus != null) { if (projectStatus != null) {
// TODO: check if this is really useful
/*
if (!validateStatus(projectStatus)) { if (!validateStatus(projectStatus)) {
logger.error("updateProjectStatus: Invalid status {}", projectStatus); logger.error("updateProjectStatus: Invalid status {}", projectStatus);
throw new ResponseStatusException( throw new ResponseStatusException(
HttpStatus.NOT_ACCEPTABLE, "Ce status n'est pas accepté"); HttpStatus.NOT_ACCEPTABLE, "Ce status n'est pas accepté");
} }
*/
project.get().setProjectStatus(projectStatus); project.get().setProjectStatus(projectStatus);
} }
@ -96,10 +102,23 @@ public class ProjectService {
} }
public Iterable<Project> getPendingProjects() { public Iterable<Project> getPendingProjects() {
return this.projectRepository.findByProjectStatus("PENDING"); return this.projectRepository.findByProjectStatus(PENDING);
} }
public void deleteProjectById(Long id) { public void deleteProjectById(Long id) {
this.projectRepository.deleteById(id); this.projectRepository.deleteById(id);
} }
public Project getProjectByName(String name, boolean noerror) {
Optional<Project> 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);
}
} }

View File

@ -1,10 +1,12 @@
package enseirb.myinpulse; package enseirb.myinpulse;
import static org.junit.jupiter.api.Assertions.assertEquals; import static enseirb.myinpulse.model.ProjectDecisionValue.*;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.*;
import enseirb.myinpulse.model.Administrator; import enseirb.myinpulse.model.Administrator;
import enseirb.myinpulse.model.Project; import enseirb.myinpulse.model.Project;
import enseirb.myinpulse.model.ProjectDecision;
import enseirb.myinpulse.service.AdminApiService; import enseirb.myinpulse.service.AdminApiService;
import enseirb.myinpulse.service.database.AdministratorService; import enseirb.myinpulse.service.database.AdministratorService;
import enseirb.myinpulse.service.database.ProjectService; import enseirb.myinpulse.service.database.ProjectService;
@ -23,7 +25,9 @@ import java.util.List;
@SpringBootTest @SpringBootTest
@Transactional @Transactional
public class AdminApiServiceTest { public class AdminApiServiceTest {
private static long administratorid;
@Autowired private AdminApiService adminApiService; @Autowired private AdminApiService adminApiService;
@Autowired private ProjectService projectService;
@BeforeAll @BeforeAll
static void setup( static void setup(
@ -36,6 +40,7 @@ public class AdminApiServiceTest {
"testAdminEmpty@example.com", "testAdminEmpty@example.com",
"testAdmin@example.com", "testAdmin@example.com",
"")); ""));
Administrator a =
administratorService.addAdministrator( administratorService.addAdministrator(
new Administrator( new Administrator(
"admin2", "admin2",
@ -43,23 +48,28 @@ public class AdminApiServiceTest {
"testAdminFull@example.com", "testAdminFull@example.com",
"testAdmin@example.com", "testAdmin@example.com",
"")); ""));
administratorid = a.getIdUser();
projectService.addNewProject( projectService.addNewProject(
new Project( new Project(
"sampleProjectAdminApiService", "sampleProjectAdminApiService",
null, null,
LocalDate.now(), LocalDate.now(),
"ONGOING", ACTIVE,
administratorService.getAdministratorByPrimaryMain( administratorService.getAdministratorByPrimaryMain(
"testAdminFull@example.com"))); "testAdminFull@example.com")));
} }
private <T> List<T> IterableToList(Iterable<T> iterable) {
List<T> l = new ArrayList<>();
iterable.forEach(l::add);
return l;
}
@Test @Test
void getProjectOfAdminIsEmpty() { void getProjectOfAdminIsEmpty() {
Iterable<Project> projects = Iterable<Project> projects =
adminApiService.getProjectsOfAdmin("testAdminEmpty@example.com"); adminApiService.getProjectsOfAdmin("testAdminEmpty@example.com");
List<Project> l = new ArrayList<>(); assertEquals(0, IterableToList(projects).size());
projects.forEach(l::add);
assertEquals(0, l.size());
} }
@Test @Test
@ -77,10 +87,87 @@ public class AdminApiServiceTest {
void getProjectOfAdminNotEmpty() { void getProjectOfAdminNotEmpty() {
Iterable<Project> projects = Iterable<Project> projects =
adminApiService.getProjectsOfAdmin("testAdminFull@example.com"); adminApiService.getProjectsOfAdmin("testAdminFull@example.com");
List<Project> l = new ArrayList<>(); List<Project> l = IterableToList(projects);
projects.forEach(l::add);
assertEquals(1, l.size()); assertEquals(1, l.size());
Project p = l.getFirst(); Project p = l.getFirst();
assertEquals(p.getProjectName(), "sampleProjectAdminApiService"); 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<Project> pendingProjects = this.adminApiService.getPendingProjects();
List<Project> 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));
}
} }