From 5392c72974c93d8ba40d48968a8eb54d5e4c291b Mon Sep 17 00:00:00 2001 From: VasylyshynDmytro Date: Mon, 16 Dec 2024 12:44:39 +0200 Subject: [PATCH] Fix --- .../greencity/controller/PlaceController.java | 12 +- .../controller/PlaceControllerTest.java | 141 +++++++----------- .../greencity/service/PlaceServiceImpl.java | 15 ++ .../service/PlaceServiceImplTest.java | 5 +- 4 files changed, 75 insertions(+), 98 deletions(-) diff --git a/core/src/main/java/greencity/controller/PlaceController.java b/core/src/main/java/greencity/controller/PlaceController.java index 5da392aac..2d4e4fe88 100644 --- a/core/src/main/java/greencity/controller/PlaceController.java +++ b/core/src/main/java/greencity/controller/PlaceController.java @@ -2,7 +2,6 @@ import greencity.annotations.ApiPageable; import greencity.annotations.CurrentUser; -import greencity.client.RestClient; import greencity.constant.HttpStatuses; import greencity.dto.PageableDto; import greencity.dto.favoriteplace.FavoritePlaceDto; @@ -22,6 +21,7 @@ import greencity.dto.place.AddPlaceDto; import greencity.dto.user.UserVO; import greencity.enums.PlaceStatus; +import greencity.exception.exceptions.NotFoundException; import greencity.service.FavoritePlaceService; import greencity.service.PlaceService; import io.swagger.v3.oas.annotations.Operation; @@ -68,7 +68,6 @@ public class PlaceController { */ private final PlaceService placeService; private final ModelMapper modelMapper; - private final RestClient restClient; /** * The controller which returns new proposed {@code Place} from user. @@ -307,11 +306,12 @@ public ResponseEntity> getFilteredPlaces( }) @PatchMapping("/status") public ResponseEntity updateStatus(@Valid @RequestBody UpdatePlaceStatusWithUserEmailDto dto) { - if (dto.getNewStatus() == PlaceStatus.APPROVED || dto.getNewStatus() == PlaceStatus.DECLINED) { - restClient.sendEmailNotificationChangesPlaceStatus(dto); + try { + placeService.updatePlaceStatus(dto); + return ResponseEntity.ok("Status updated successfully for place: " + dto.getPlaceName()); + } catch (NotFoundException ex) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ex.getMessage()); } - placeService.updatePlaceStatus(dto); - return ResponseEntity.ok("Status updated successfully for place: " + dto.getPlaceName()); } /** diff --git a/core/src/test/java/greencity/controller/PlaceControllerTest.java b/core/src/test/java/greencity/controller/PlaceControllerTest.java index 82bc8cdd5..7e804085b 100644 --- a/core/src/test/java/greencity/controller/PlaceControllerTest.java +++ b/core/src/test/java/greencity/controller/PlaceControllerTest.java @@ -4,12 +4,12 @@ import greencity.dto.place.PlaceAddDto; import greencity.dto.place.PlaceUpdateDto; import greencity.dto.place.PlaceVO; -import greencity.dto.place.UpdatePlaceStatusWithUserEmailDto; import greencity.dto.place.AddPlaceDto; import greencity.dto.place.BulkUpdatePlaceStatusDto; import greencity.dto.place.PlaceWithUserDto; -import greencity.entity.Place; +import greencity.dto.place.UpdatePlaceStatusWithUserEmailDto; import greencity.enums.PlaceStatus; +import greencity.exception.exceptions.NotFoundException; import greencity.service.UserService; import java.security.Principal; import java.time.DayOfWeek; @@ -57,10 +57,10 @@ import static greencity.ModelUtils.getUserVO; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.doNothing; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; @@ -589,124 +589,83 @@ void getAllPlaces() throws Exception { } @Test - void updateStatusWithApprovedStatusAPPROVED() throws Exception { - UpdatePlaceStatusWithUserEmailDto dto = new UpdatePlaceStatusWithUserEmailDto(); - dto.setPlaceName("testPlace"); - dto.setNewStatus(PlaceStatus.APPROVED); - dto.setUserName("testUser"); - dto.setEmail("user@example.com"); - String expectedResponse = "Status updated successfully for place: testPlace"; - when(placeService.updatePlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class))) - .thenReturn(dto); - doNothing().when(restClient) - .sendEmailNotificationChangesPlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class)); + void updateStatusSuccessfulTest() throws Exception { String json = """ - { - "placeName": "testPlace", - "newStatus": "APPROVED", - "userName": "testUser", - "email": "user@example.com" - } + { + "placeName": "Test Place", + "newStatus": "APPROVED", + "userName": "Test User", + "email": "test@example.com" + } """; + UpdatePlaceStatusWithUserEmailDto mockDto = new UpdatePlaceStatusWithUserEmailDto(); + mockDto.setPlaceName("Test Place"); + mockDto.setNewStatus(PlaceStatus.APPROVED); + mockDto.setUserName("Test User"); + mockDto.setEmail("test@example.com"); + when(placeService.updatePlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class))).thenReturn(mockDto); mockMvc.perform(patch(placeLink + "/status") .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isOk()) - .andExpect(content().string(expectedResponse)); + .andExpect(content().string("Status updated successfully for place: Test Place")); verify(placeService, times(1)).updatePlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class)); - verify(restClient, times(1)) - .sendEmailNotificationChangesPlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class)); } @Test - void updateStatusWithApprovedStatusDECLINED() throws Exception { - UpdatePlaceStatusWithUserEmailDto dto = new UpdatePlaceStatusWithUserEmailDto(); - dto.setPlaceName("testPlace"); - dto.setNewStatus(PlaceStatus.DECLINED); - dto.setUserName("testUser"); - dto.setEmail("user@example.com"); - String expectedResponse = "Status updated successfully for place: testPlace"; - when(placeService.updatePlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class))) - .thenReturn(dto); - doNothing().when(restClient) - .sendEmailNotificationChangesPlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class)); + void updateStatusInvalidInputTest() throws Exception { String json = """ - { - "placeName": "testPlace", - "newStatus": "DECLINED", - "userName": "testUser", - "email": "user@example.com" - } + { + "placeName": "", + "newStatus": "APPROVED", + "userName": "Test User", + "email": "invalid-email" + } """; mockMvc.perform(patch(placeLink + "/status") .contentType(MediaType.APPLICATION_JSON) .content(json)) - .andExpect(status().isOk()) - .andExpect(content().string(expectedResponse)); - verify(placeService, times(1)).updatePlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class)); - verify(restClient, times(1)) - .sendEmailNotificationChangesPlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class)); + .andExpect(status().isBadRequest()); + verify(placeService, times(0)).updatePlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class)); } @Test - void updateStatusDoesNotSendNotificationButSavesDataWhenStatusIsPROPOSED() throws Exception { - UpdatePlaceStatusWithUserEmailDto dto = new UpdatePlaceStatusWithUserEmailDto(); - dto.setPlaceName("testPlace"); - dto.setNewStatus(PlaceStatus.PROPOSED); - dto.setUserName("testUser"); - dto.setEmail("user@example.com"); - Place place = new Place(); - place.setId(1L); - place.setName("testPlace"); - place.setStatus(PlaceStatus.PROPOSED); - when(placeService.updatePlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class))).thenReturn(dto); + void updateStatusPlaceNotFoundTest() throws Exception { String json = """ - { - "placeName": "testPlace", - "newStatus": "PROPOSED", - "userName": "testUser", - "email": "user@example.com" - } + { + "placeName": "Nonexistent Place", + "newStatus": "DECLINED", + "userName": "Test User", + "email": "test@example.com" + } """; - - mockMvc.perform(patch(placeLink + "/status") + doThrow(new NotFoundException("Place not found")) + .when(placeService).updatePlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class)); + mockMvc.perform(patch("/place/status") .contentType(MediaType.APPLICATION_JSON) .content(json)) - .andExpect(status().isOk()) - .andExpect(content().string("Status updated successfully for place: testPlace")); + .andExpect(status().isNotFound()) + .andExpect(content().string("Place not found")); verify(placeService, times(1)).updatePlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class)); - verify(restClient, times(0)) - .sendEmailNotificationChangesPlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class)); } @Test - void updateStatusDoesNotSendNotificationButSavesDataWhenStatusIsDELETED() throws Exception { - UpdatePlaceStatusWithUserEmailDto dto = new UpdatePlaceStatusWithUserEmailDto(); - dto.setPlaceName("testPlace"); - dto.setNewStatus(PlaceStatus.DELETED); - dto.setUserName("testUser"); - dto.setEmail("user@example.com"); - Place place = new Place(); - place.setId(1L); - place.setName("testPlace"); - place.setStatus(PlaceStatus.DELETED); - when(placeService.updatePlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class))).thenReturn(dto); + void updateStatusUserNotFoundTest() throws Exception { String json = """ - { - "placeName": "testPlace", - "newStatus": "DELETED", - "userName": "testUser", - "email": "user@example.com" - } + { + "placeName": "Test Place", + "newStatus": "DECLINED", + "userName": "Test User", + "email": "nonexistent@example.com" + } """; - - mockMvc.perform(patch(placeLink + "/status") + doThrow(new NotFoundException("User not found")) + .when(placeService).updatePlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class)); + mockMvc.perform(patch("/place/status") .contentType(MediaType.APPLICATION_JSON) .content(json)) - .andExpect(status().isOk()) - .andExpect(content().string("Status updated successfully for place: testPlace")); + .andExpect(status().isNotFound()) + .andExpect(content().string("User not found")); verify(placeService, times(1)).updatePlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class)); - verify(restClient, times(0)) - .sendEmailNotificationChangesPlaceStatus(any(UpdatePlaceStatusWithUserEmailDto.class)); } } diff --git a/service/src/main/java/greencity/service/PlaceServiceImpl.java b/service/src/main/java/greencity/service/PlaceServiceImpl.java index 9261c426f..b37add714 100644 --- a/service/src/main/java/greencity/service/PlaceServiceImpl.java +++ b/service/src/main/java/greencity/service/PlaceServiceImpl.java @@ -1,6 +1,7 @@ package greencity.service; import com.google.maps.model.GeocodingResult; +import greencity.client.RestClient; import greencity.constant.ErrorMessage; import greencity.constant.LogMessage; import greencity.dto.PageableDto; @@ -100,6 +101,7 @@ public class PlaceServiceImpl implements PlaceService { private final FavoritePlaceRepo favoritePlaceRepo; private final FileService fileService; private final UserNotificationService userNotificationService; + private final RestClient restClient; /** * {@inheritDoc} @@ -637,6 +639,15 @@ private PageableDto getSearchPlacesDtoPageableDto(Page p page.getTotalPages()); } + /** + * Updates the status of a place, validates the user's existence, and sends a + * notification if the status changes to APPROVED or DECLINED. + * + * @param dto The data transfer object containing place name, user email, and + * the new status. + * @return The updated UpdatePlaceStatusWithUserEmailDto. + * @throws NotFoundException If the place or user is not found. + */ @Override public UpdatePlaceStatusWithUserEmailDto updatePlaceStatus(UpdatePlaceStatusWithUserEmailDto dto) { Place place = placeRepo.findByNameIgnoreCase(dto.getPlaceName()) @@ -648,6 +659,10 @@ public UpdatePlaceStatusWithUserEmailDto updatePlaceStatus(UpdatePlaceStatusWith place.setStatus(dto.getNewStatus()); placeRepo.save(place); + + if (dto.getNewStatus() == PlaceStatus.APPROVED || dto.getNewStatus() == PlaceStatus.DECLINED) { + restClient.sendEmailNotificationChangesPlaceStatus(dto); + } return dto; } } \ No newline at end of file diff --git a/service/src/test/java/greencity/service/PlaceServiceImplTest.java b/service/src/test/java/greencity/service/PlaceServiceImplTest.java index 9c9eec70b..dffbce029 100644 --- a/service/src/test/java/greencity/service/PlaceServiceImplTest.java +++ b/service/src/test/java/greencity/service/PlaceServiceImplTest.java @@ -1,6 +1,7 @@ package greencity.service; import greencity.ModelUtils; +import greencity.client.RestClient; import greencity.dto.PageableDto; import greencity.dto.category.CategoryDto; import greencity.dto.category.CategoryDtoResponse; @@ -195,13 +196,15 @@ class PlaceServiceImplTest { private FileService fileService; @Mock private UserNotificationService userNotificationService; + @Mock + private RestClient restClient; @BeforeEach void init() { placeService = new PlaceServiceImpl(placeRepo, modelMapper, categoryService, locationService, specificationService, openingHoursService, userService, discountService, zoneId, proposePlaceMapper, categoryRepo, googleApiService, userRepo, favoritePlaceRepo, fileService, - userNotificationService); + userNotificationService, restClient); } @Test