From 933ac666a8b61382693103dcc3eb3bb283582bbc Mon Sep 17 00:00:00 2001 From: Rajbir Singh Date: Wed, 23 Oct 2024 13:16:39 +0200 Subject: [PATCH 1/3] PMT-26: Define Endpoint --- api/pmt.yml | 72 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/api/pmt.yml b/api/pmt.yml index 0e803c0..e29a938 100644 --- a/api/pmt.yml +++ b/api/pmt.yml @@ -77,6 +77,45 @@ components: qualificationId: type: integer format: int64 + Employee: + type: object + properties: + id: + type: integer + format: int64 + lastName: + type: string + firstName: + type: string + street: + type: string + postcode: + maxLength: 5 + minLength: 5 + type: string + city: + type: string + phone: + type: string + skillSet: + type: array + items: + $ref: '#/components/schemas/Qualification' + Qualification: + type: object + properties: + skill: + type: string + id: + type: integer + format: int64 + ProjectEmployeesDTO: + type: object + properties: + employees: + type: array + items: + $ref: "#/components/schemas/Employee" responses: Unauthorized: description: "Unauthorized" @@ -167,10 +206,10 @@ paths: format: int64 required: true requestBody: - content: - application/json: - schema: - $ref: "#/components/schemas/AddEmployeeDTO" + content: + application/json: + schema: + $ref: "#/components/schemas/AddEmployeeDTO" responses: 204: description: "Employee successfully added to the specific Project" @@ -179,7 +218,7 @@ paths: 404: $ref: "#/components/responses/NotFound" 409: - $ref: "#/components/responses/Conflict" + $ref: "#/components/responses/Conflict" 422: $ref: "#/components/responses/UnprocessableContent" 500: @@ -241,3 +280,26 @@ paths: $ref: "#/components/responses/InternalError" 503: $ref: "#/components/responses/ServiceUnavailable" + + /project/{id}/employees: + get: + description: "getAllEmployees" + operationId: "Get a List of all Employees from a specific Project" + parameters: + - in: path + name: id + schema: + type: integer + format: int64 + required: true + responses: + 200: + content: + application/json: + schema: + $ref: "#/components/schemas/ProjectEmployeesDTO" + description: 'Get a List of all Employees from a specific Project ' + 404: + $ref: '#/components/responses/NotFound' + 500: + $ref: "#/components/responses/InternalError" -- 2.45.2 From b9d317080238e3d52e54be854e8670dd9f338103 Mon Sep 17 00:00:00 2001 From: Rajbir Singh Date: Wed, 23 Oct 2024 13:17:04 +0200 Subject: [PATCH 2/3] PMT-26: Implement Endpoint --- src/main/java/de/hmmh/pmt/ApiController.java | 32 ++++++++++++++++++-- src/main/java/de/hmmh/pmt/util/Mapper.java | 32 ++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/hmmh/pmt/ApiController.java b/src/main/java/de/hmmh/pmt/ApiController.java index 5d2a8f4..6c57d91 100644 --- a/src/main/java/de/hmmh/pmt/ApiController.java +++ b/src/main/java/de/hmmh/pmt/ApiController.java @@ -19,8 +19,8 @@ import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestClientException; import java.time.ZoneOffset; -import java.util.List; -import java.util.Optional; +import java.util.*; +import java.util.stream.Collectors; @Controller @RequestMapping("${openapi.projectManagement.base-path:/api/v1}") @@ -153,4 +153,32 @@ public class ApiController implements DefaultApi { allocationRepository.delete(allocation.get()); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } + + @Override + public ResponseEntity getAListOfAllEmployeesFromASpecificProject(Long id) { + if (!projectRepository.existsById(id)) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + + ProjectEmployeesDTO dto = new ProjectEmployeesDTO(); + List allocationsByProject = allocationRepository.findAllByProjectId(id); + if (allocationsByProject.isEmpty()) { + return new ResponseEntity<>(dto, HttpStatus.OK); + } + + Set employeeIds = allocationsByProject.stream() + .map(Allocation::getEmployeeId) + .collect(Collectors.toSet()); + + try { + List employees = apiClientFactory.getEmployeeApi().findAll1().stream() + .filter(employeeResponseDTO -> employeeIds.contains(employeeResponseDTO.getId())) + .map(mapper::map) + .toList(); + dto.setEmployees(employees); + return new ResponseEntity<>(dto, HttpStatus.OK); + } catch (RestClientException exception) { + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + } } diff --git a/src/main/java/de/hmmh/pmt/util/Mapper.java b/src/main/java/de/hmmh/pmt/util/Mapper.java index d5d7591..09ba201 100644 --- a/src/main/java/de/hmmh/pmt/util/Mapper.java +++ b/src/main/java/de/hmmh/pmt/util/Mapper.java @@ -3,8 +3,14 @@ package de.hmmh.pmt.util; import de.hmmh.pmt.db.Project; import de.hmmh.pmt.dtos.CreateProjectDTO; import de.hmmh.pmt.dtos.CreatedProjectDTO; +import de.hmmh.pmt.dtos.Employee; +import de.hmmh.pmt.dtos.Qualification ; +import de.hmmh.pmt.employee.dtos.EmployeeResponseDTO; +import de.hmmh.pmt.employee.dtos.QualificationGetDTO; import org.springframework.stereotype.Component; +import java.util.List; + @Component public class Mapper { public Project map(CreateProjectDTO dto) { @@ -29,4 +35,30 @@ public class Mapper { dto.setPlannedEnd(project.getPlannedEnd()); return dto; } + + public Employee map(EmployeeResponseDTO employeeResponseDTO) { + Employee dto = new Employee(); + dto.setId(employeeResponseDTO.getId()); + dto.setLastName(employeeResponseDTO.getLastName()); + dto.setFirstName(employeeResponseDTO.getFirstName()); + dto.setStreet(employeeResponseDTO.getStreet()); + dto.setPostcode(employeeResponseDTO.getPostcode()); + dto.setCity(employeeResponseDTO.getCity()); + dto.setPhone(employeeResponseDTO.getPhone()); + + List skillSet = employeeResponseDTO.getSkillSet().stream() + .map(this::map) + .toList(); + + dto.setSkillSet(skillSet); + return dto; + } + + private Qualification map(QualificationGetDTO qualificationGetDTO) { + Qualification dto = new Qualification (); + dto.setId(qualificationGetDTO.getId()); + dto.setSkill(qualificationGetDTO.getSkill()); + return dto; + } + } -- 2.45.2 From 108a31b2faa1a15d3510161aa32c38b7b8277dbb Mon Sep 17 00:00:00 2001 From: Rajbir Singh Date: Wed, 23 Oct 2024 13:17:23 +0200 Subject: [PATCH 3/3] PMT-26: Test Endpoint --- .../java/de/hmmh/pmt/IntegrationTest.java | 9 ++- .../project/GetAllEmployeesByProjectTest.java | 66 +++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 src/test/java/de/hmmh/pmt/project/GetAllEmployeesByProjectTest.java diff --git a/src/test/java/de/hmmh/pmt/IntegrationTest.java b/src/test/java/de/hmmh/pmt/IntegrationTest.java index 65e98f0..26ccee2 100644 --- a/src/test/java/de/hmmh/pmt/IntegrationTest.java +++ b/src/test/java/de/hmmh/pmt/IntegrationTest.java @@ -165,13 +165,18 @@ public abstract class IntegrationTest { allocation1ToOverlapA.setRole(TEST_QUALIFICATION_A_ID); allocations.put("1>overlap-a", allocation1ToOverlapA); - Allocation allocation1ToSpaceStation = new Allocation(); allocation1ToSpaceStation.setProject(allProjects.get("space-station")); allocation1ToSpaceStation.setEmployeeId(TEST_EMPLOYEE_A_ID); allocation1ToSpaceStation.setRole(TEST_QUALIFICATION_A_ID); allocations.put("1>space-station", allocation1ToSpaceStation); - + + Allocation allocation1ToAiResearch = new Allocation(); + allocation1ToAiResearch.setProject(allProjects.get("ai-research")); + allocation1ToAiResearch.setEmployeeId(TEST_EMPLOYEE_A_ID); + allocation1ToAiResearch.setRole(TEST_QUALIFICATION_A_ID); + allocations.put("1>ai-research", allocation1ToAiResearch); + allocationRepository.saveAllAndFlush(allocations.values()); return allocations; } diff --git a/src/test/java/de/hmmh/pmt/project/GetAllEmployeesByProjectTest.java b/src/test/java/de/hmmh/pmt/project/GetAllEmployeesByProjectTest.java new file mode 100644 index 0000000..01a9406 --- /dev/null +++ b/src/test/java/de/hmmh/pmt/project/GetAllEmployeesByProjectTest.java @@ -0,0 +1,66 @@ +package de.hmmh.pmt.project; + +import de.hmmh.pmt.IntegrationTest; +import de.hmmh.pmt.db.Project; +import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.RequestBuilder; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.web.client.RestClientException; + + +import java.util.Map; + + +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +public class GetAllEmployeesByProjectTest extends IntegrationTest { + + @Test + void shouldReturnNotFoundWhenProjectDoesNotExist() throws Exception { + createTestProjectData(); + + this.mvc + .perform(getRequest(50L)) + .andExpect(status().isNotFound()); + } + + @Test + void shouldReturnOkWhenProjectHasNoEmployees() throws Exception { + Map allProjects = createTestProjectData(); + + this.mvc + .perform(getRequest(allProjects.get("research-lab").getId())) + .andExpect(status().isOk()); + } + + @Test + void shouldReturnListOfEmployeesWhenAllParametersAreValid() throws Exception { + Map allProjects = createTestProjectData(); + createTestAllocationData(allProjects); + + this.mvc + .perform(getRequest(allProjects.get("ai-research").getId())) + .andExpect(status().isOk()); + } + + @Test + void shouldReturnInternalServer() throws Exception { + when(this.mockEmployeeApi.findAll1()) + .thenThrow(new RestClientException("Internal Server Error")); + + Map allProjects = createTestProjectData(); + createTestAllocationData(allProjects); + + this.mvc + .perform(getRequest(allProjects.get("ai-research").getId())) + .andExpect(status().isInternalServerError()); + } + + private RequestBuilder getRequest(Long projectId) { + return MockMvcRequestBuilders + .get(baseUri + "/project/" + projectId + "/employees") + .contentType(MediaType.APPLICATION_JSON); + } +} -- 2.45.2