diff --git a/src/main/java/hng_java_boilerplate/organisation/controller/OrganisationController.java b/src/main/java/hng_java_boilerplate/organisation/controller/OrganisationController.java index 06bbed3d2..3e92b4377 100644 --- a/src/main/java/hng_java_boilerplate/organisation/controller/OrganisationController.java +++ b/src/main/java/hng_java_boilerplate/organisation/controller/OrganisationController.java @@ -9,15 +9,12 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController @RequiredArgsConstructor @RequestMapping("/api/v1/organisations") -@Tag(name="Organisation") +@Tag(name = "Organisation") public class OrganisationController { private final OrganisationService organisationService; @@ -30,4 +27,15 @@ public ResponseEntity createOrganisation( organisationService.create(orgRequest, activeUser) ); } + + @GetMapping("/{org_id}/users") + public ResponseEntity getOrganisationUsers(@PathVariable(name = "org_id") String orgId, + @RequestParam(name = "page", defaultValue = "0") int page, + @RequestParam(name = "size", defaultValue = "10") int pageSize) { + try { + return ResponseEntity.ok(organisationService.getOrganisationUsers(orgId, page, pageSize)); + } catch (Exception e) { + return ResponseEntity.badRequest().body(e.getMessage()); + } + } } diff --git a/src/main/java/hng_java_boilerplate/organisation/dto/ApiResponseDTO.java b/src/main/java/hng_java_boilerplate/organisation/dto/ApiResponseDTO.java new file mode 100644 index 000000000..a28c64e4f --- /dev/null +++ b/src/main/java/hng_java_boilerplate/organisation/dto/ApiResponseDTO.java @@ -0,0 +1,14 @@ +package hng_java_boilerplate.organisation.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class ApiResponseDTO { + @JsonProperty("status_code") + private int statusCode; + private String message; + private Object data; +} \ No newline at end of file diff --git a/src/main/java/hng_java_boilerplate/organisation/service/OrganisationService.java b/src/main/java/hng_java_boilerplate/organisation/service/OrganisationService.java index 3c42f1c03..3eedf45bd 100644 --- a/src/main/java/hng_java_boilerplate/organisation/service/OrganisationService.java +++ b/src/main/java/hng_java_boilerplate/organisation/service/OrganisationService.java @@ -1,18 +1,26 @@ package hng_java_boilerplate.organisation.service; import hng_java_boilerplate.activitylog.service.ActivityLogService; +import hng_java_boilerplate.organisation.dto.ApiResponseDTO; import hng_java_boilerplate.organisation.dto.CreateOrganisationRequestDto; import hng_java_boilerplate.organisation.dto.CreateOrganisationResponseDto; import hng_java_boilerplate.organisation.dto.DataDto; import hng_java_boilerplate.organisation.entity.Organisation; import hng_java_boilerplate.organisation.exception.OrganisationNameAlreadyExistsException; import hng_java_boilerplate.organisation.repository.OrganisationRepository; +import hng_java_boilerplate.user.dto.request.GetUserDto; import hng_java_boilerplate.user.entity.User; import hng_java_boilerplate.user.repository.UserRepository; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.server.ResponseStatusException; import java.time.LocalDateTime; import java.util.List; @@ -80,4 +88,36 @@ public CreateOrganisationResponseDto create( .status_code(201) .build(); } + + public ResponseEntity getOrganisationUsers(String orgId, int page, int pageSize) { + organisationRepository.findById(orgId) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Organisation not found")); + + Pageable pageable = PageRequest.of(page, pageSize); + Page users = userRepository.findByOrganisations_Id(orgId, pageable); + + if (users.isEmpty()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(ApiResponseDTO.builder() + .statusCode(400) + .message("No users found for organisation with ID: " + orgId) + .data(null) + .build()); + } + + List userDtoList = users.getContent().stream() + .map(user -> GetUserDto.builder() + .id(user.getId()) + .name(user.getName()) + .email(user.getEmail()) + .build()) + .toList(); + + return ResponseEntity.status(HttpStatus.OK) + .body(ApiResponseDTO.builder() + .statusCode(200) + .message("Users retrieved successfully for organisation with ID: " + orgId) + .data(userDtoList) + .build()); + } } diff --git a/src/main/java/hng_java_boilerplate/user/repository/UserRepository.java b/src/main/java/hng_java_boilerplate/user/repository/UserRepository.java index 42a0e9a7e..ad6cc202a 100644 --- a/src/main/java/hng_java_boilerplate/user/repository/UserRepository.java +++ b/src/main/java/hng_java_boilerplate/user/repository/UserRepository.java @@ -2,7 +2,10 @@ import hng_java_boilerplate.user.entity.User; import hng_java_boilerplate.user.enums.Role; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.web.bind.annotation.RequestParam; import java.util.List; import java.util.Optional; @@ -17,4 +20,6 @@ public interface UserRepository extends JpaRepository { void deleteByEmail(String mail); List findUserByUserRole(Role role); + + Page findByOrganisations_Id( String orgId, Pageable pageable); } diff --git a/src/test/java/hng_java_boilerplate/organisation/service/OrganisationServiceTest.java b/src/test/java/hng_java_boilerplate/organisation/service/OrganisationServiceTest.java index f97d7e9f4..1e629fb93 100644 --- a/src/test/java/hng_java_boilerplate/organisation/service/OrganisationServiceTest.java +++ b/src/test/java/hng_java_boilerplate/organisation/service/OrganisationServiceTest.java @@ -1,6 +1,7 @@ package hng_java_boilerplate.organisation.service; import hng_java_boilerplate.activitylog.service.ActivityLogService; +import hng_java_boilerplate.organisation.dto.ApiResponseDTO; import hng_java_boilerplate.organisation.dto.CreateOrganisationRequestDto; import hng_java_boilerplate.organisation.dto.CreateOrganisationResponseDto; import hng_java_boilerplate.organisation.entity.Organisation; @@ -9,6 +10,7 @@ import hng_java_boilerplate.organisation.exception.OrganisationNameAlreadyExistsException; import hng_java_boilerplate.organisation.exception.ValidationError; import hng_java_boilerplate.organisation.repository.OrganisationRepository; +import hng_java_boilerplate.user.dto.request.GetUserDto; import hng_java_boilerplate.user.entity.User; import hng_java_boilerplate.user.repository.UserRepository; import org.junit.jupiter.api.BeforeEach; @@ -17,6 +19,9 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; @@ -52,6 +57,8 @@ class OrganisationServiceTest { private CreateOrganisationRequestDto orgRequest; private User user; + private Organisation organisation; + @BeforeEach void setUp() { orgRequest = new CreateOrganisationRequestDto( @@ -66,6 +73,15 @@ void setUp() { ); user = new User(); user.setId("user-123"); + + organisation = new Organisation(); + organisation.setId("org-123"); + organisation.setName("Test Organisation"); + + user = new User(); + user.setId("user-123"); + user.setName("John Doe"); + user.setEmail("john.doe@example.com"); } @Test @@ -130,4 +146,54 @@ void create_shouldThrowValidationException_whenRequestIsInvalid() { assertEquals("Name must not be empty", errors.get(0).message()); } + @Test + void getOrganisationUsers_shouldReturnNotFound_whenOrganisationDoesNotExist() { + when(organisationRepository.findById("org-123")).thenReturn(Optional.empty()); + + Exception exception = assertThrows(Exception.class, () -> + organisationService.getOrganisationUsers("org-123", 0, 10) + ); + + assertEquals("404 NOT_FOUND \"Organisation not found\"", exception.getMessage()); + verify(organisationRepository, times(1)).findById("org-123"); + } + + @Test + void getOrganisationUsers_shouldReturnNotFound_whenNoUsersFound() { + when(organisationRepository.findById("org-123")).thenReturn(Optional.of(organisation)); + when(userRepository.findByOrganisations_Id("org-123", PageRequest.of(0, 10))) + .thenReturn(Page.empty()); + + ResponseEntity response = organisationService.getOrganisationUsers("org-123", 0, 10); + + assertNotNull(response); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + assertEquals(400, response.getBody().getStatusCode()); + assertEquals("No users found for organisation with ID: org-123", response.getBody().getMessage()); + assertNull(response.getBody().getData()); + } + + @Test + void getOrganisationUsers_shouldReturnUsers_whenUsersExist() { + when(organisationRepository.findById("org-123")).thenReturn(Optional.of(organisation)); + List users = List.of(user); + Page userPage = new PageImpl<>(users); + when(userRepository.findByOrganisations_Id("org-123", PageRequest.of(0, 10))) + .thenReturn(userPage); + + ResponseEntity response = organisationService.getOrganisationUsers("org-123", 0, 10); + + assertNotNull(response); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertEquals(200, response.getBody().getStatusCode()); + assertEquals("Users retrieved successfully for organisation with ID: org-123", response.getBody().getMessage()); + assertNotNull(response.getBody().getData()); + + List userDtos = (List) response.getBody().getData(); + assertEquals(1, userDtos.size()); + assertEquals("user-123", userDtos.get(0).getId()); + assertEquals("John Doe", userDtos.get(0).getName()); + assertEquals("john.doe@example.com", userDtos.get(0).getEmail()); + } + } \ No newline at end of file