From 544a6c4dfd3692be0c5cfa01473eea6d6fe98d62 Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Sat, 19 Aug 2023 18:30:51 +0300 Subject: [PATCH 01/21] `AysLocationUtil` Class Has Been Created for Logical Methods of Location --- .../ays/location/util/AysLocationUtil.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/com/ays/location/util/AysLocationUtil.java diff --git a/src/main/java/com/ays/location/util/AysLocationUtil.java b/src/main/java/com/ays/location/util/AysLocationUtil.java new file mode 100644 index 000000000..a3908ecf6 --- /dev/null +++ b/src/main/java/com/ays/location/util/AysLocationUtil.java @@ -0,0 +1,28 @@ +package com.ays.location.util; + +import lombok.experimental.UtilityClass; +import org.locationtech.jts.geom.*; +import org.locationtech.jts.geom.impl.CoordinateArraySequence; + +/** + * Utility class for handling location-related operations. + * Provides methods to generate geometric points based on latitude and longitude coordinates. + */ +@UtilityClass +public class AysLocationUtil { + + /** + * Generates a Point object representing a location based on the provided latitude and longitude coordinates. + * + * @param latitude The latitude coordinate of the location. + * @param longitude The longitude coordinate of the location. + * @return A Point object representing the location. + */ + public static Point generatePoint(final Double latitude, final Double longitude) { + final Coordinate[] coordinates = new Coordinate[]{new Coordinate(latitude, longitude)}; + final CoordinateSequence coordinateSequence = new CoordinateArraySequence(coordinates); + final PrecisionModel precisionModel = new PrecisionModel(PrecisionModel.FLOATING); + return new GeometryFactory(precisionModel, 4326).createPoint(coordinateSequence); + } + +} From dfd4d8bc8a3fa03be9c9038f910016d5395835f3 Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Sat, 19 Aug 2023 18:31:43 +0300 Subject: [PATCH 02/21] `UserLocationEntity.setPoint()` Has Been Updated with `AysLocationUtil` Classes --- .../ays/location/model/entity/UserLocationEntity.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/ays/location/model/entity/UserLocationEntity.java b/src/main/java/com/ays/location/model/entity/UserLocationEntity.java index 30fb893ea..cb2be3a6e 100644 --- a/src/main/java/com/ays/location/model/entity/UserLocationEntity.java +++ b/src/main/java/com/ays/location/model/entity/UserLocationEntity.java @@ -1,6 +1,7 @@ package com.ays.location.model.entity; import com.ays.common.model.entity.BaseEntity; +import com.ays.location.util.AysLocationUtil; import com.ays.user.model.entity.UserEntity; import jakarta.persistence.*; import lombok.AllArgsConstructor; @@ -8,8 +9,6 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; -import org.locationtech.jts.geom.Coordinate; -import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.Point; /** @@ -35,14 +34,13 @@ public class UserLocationEntity extends BaseEntity { @Column(name = "POINT", columnDefinition = "ST_GeomFromText(Point, 4326)") private Point point; + @OneToOne @JoinColumn(name = "USER_ID", referencedColumnName = "ID", insertable = false, updatable = false) private UserEntity user; - public void setPoint(double latitude, double longitude) { - Coordinate coordinate = new Coordinate(latitude, longitude); - GeometryFactory geometryFactory = new GeometryFactory(); - this.point = geometryFactory.createPoint(coordinate); + public void setPoint(final Double latitude, final Double longitude) { + this.point = AysLocationUtil.generatePoint(latitude, longitude); } } From 7cc0d41dd7e631b3dc02cd4f89105406d0ebd178 Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Sat, 19 Aug 2023 18:33:24 +0300 Subject: [PATCH 03/21] `UserLocationSaveRequest` Has Been Created and Validation Annotations Have Been Added --- ...onRequest.java => UserLocationSaveRequest.java} | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) rename src/main/java/com/ays/location/model/dto/request/{UserLocationRequest.java => UserLocationSaveRequest.java} (68%) diff --git a/src/main/java/com/ays/location/model/dto/request/UserLocationRequest.java b/src/main/java/com/ays/location/model/dto/request/UserLocationSaveRequest.java similarity index 68% rename from src/main/java/com/ays/location/model/dto/request/UserLocationRequest.java rename to src/main/java/com/ays/location/model/dto/request/UserLocationSaveRequest.java index 499bca3f0..b9be51ca4 100644 --- a/src/main/java/com/ays/location/model/dto/request/UserLocationRequest.java +++ b/src/main/java/com/ays/location/model/dto/request/UserLocationSaveRequest.java @@ -1,10 +1,12 @@ package com.ays.location.model.dto.request; +import jakarta.validation.constraints.NotNull; import lombok.Builder; -import lombok.Data; +import lombok.Getter; +import lombok.Setter; /** - * A DTO class representing the request data for updating user location. + * A DTO class representing the request data for saving/updating user location. *

* This class provides getters and setters for the latitude, and longitude fields. * It also includes a builder pattern implementation for constructing instances of this class with optional parameters. @@ -12,11 +14,15 @@ * The purpose of this class is to encapsulate the request data related to updating user location, allowing for easy * transfer of the data between different layers of the application. */ -@Data +@Getter +@Setter @Builder -public class UserLocationRequest { +public class UserLocationSaveRequest { + @NotNull private Double latitude; + + @NotNull private Double longitude; } From 1bba732f54a2b9fea8b8832c95759a3c0eb1af26 Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Sat, 19 Aug 2023 18:34:07 +0300 Subject: [PATCH 04/21] Mapper Class Has Been Created for Converting `UserLocationSaveRequest` to `UserLocationEntity` --- ...SaveRequestToUserLocationEntityMapper.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/main/java/com/ays/location/model/mapper/UserLocationSaveRequestToUserLocationEntityMapper.java diff --git a/src/main/java/com/ays/location/model/mapper/UserLocationSaveRequestToUserLocationEntityMapper.java b/src/main/java/com/ays/location/model/mapper/UserLocationSaveRequestToUserLocationEntityMapper.java new file mode 100644 index 000000000..45d5dfab2 --- /dev/null +++ b/src/main/java/com/ays/location/model/mapper/UserLocationSaveRequestToUserLocationEntityMapper.java @@ -0,0 +1,43 @@ +package com.ays.location.model.mapper; + +import com.ays.common.model.mapper.BaseMapper; +import com.ays.location.model.dto.request.UserLocationSaveRequest; +import com.ays.location.model.entity.UserLocationEntity; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * UserLocationSaveRequestToUserLocationEntityMapper is an interface that defines the mapping between an {@link UserLocationSaveRequest} and an {@link UserLocationEntity}. + * This interface uses the MapStruct annotation @Mapper to generate an implementation of this interface at compile-time. + *

The class provides a static method {@code initialize()} that returns an instance of the generated mapper implementation. + *

The interface extends the MapStruct interface {@link BaseMapper}, which defines basic mapping methods. + * The interface adds no additional mapping methods, but simply defines the types to be used in the mapping process. + */ +@Mapper +public interface UserLocationSaveRequestToUserLocationEntityMapper extends BaseMapper { + + /** + * Maps an {@link UserLocationSaveRequest} object to an {@link UserLocationEntity} object for saving in the database. + * + * @param saveRequest the {@link UserLocationSaveRequest} object to be mapped. + * @param userId the {@link String} object. + * @return the mapped {@link UserLocationEntity} object. + */ + default UserLocationEntity mapForSaving(UserLocationSaveRequest saveRequest, String userId) { + final UserLocationEntity userLocationEntity = UserLocationEntity.builder() + .userId(userId) + .build(); + userLocationEntity.setPoint(saveRequest.getLatitude(), saveRequest.getLongitude()); + return userLocationEntity; + } + + /** + * Initializes the mapper. + * + * @return the initialized mapper object. + */ + static UserLocationSaveRequestToUserLocationEntityMapper initialize() { + return Mappers.getMapper(UserLocationSaveRequestToUserLocationEntityMapper.class); + } + +} From ccf82eefa37acde6d85e30458d0fb75c7bdc675c Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Sat, 19 Aug 2023 18:35:17 +0300 Subject: [PATCH 05/21] `findByUserId()` Method Has Been Added to `UserLocationRepository` Class --- .../location/repository/UserLocationRepository.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/ays/location/repository/UserLocationRepository.java b/src/main/java/com/ays/location/repository/UserLocationRepository.java index 7e35939f8..6f55149a4 100644 --- a/src/main/java/com/ays/location/repository/UserLocationRepository.java +++ b/src/main/java/com/ays/location/repository/UserLocationRepository.java @@ -3,9 +3,19 @@ import com.ays.location.model.entity.UserLocationEntity; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + /** * Repository interface for performing CRUD operations on UserLocationEntity objects. */ public interface UserLocationRepository extends JpaRepository { + /** + * Retrieves the user's location entity based on the provided user ID. + * + * @param userId The unique identifier of the user. + * @return An Optional containing the user's location entity if found, or an empty Optional if not found. + */ + Optional findByUserId(String userId); + } From 608a85cb856f3d02b3f72bf6c78a5bc30f6c5e21 Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Sat, 19 Aug 2023 18:35:58 +0300 Subject: [PATCH 06/21] Save Latest Location of User Flow Has Been Created in Service Layer --- .../location/service/UserLocationService.java | 18 +++++++ .../service/impl/UserLocationServiceImpl.java | 49 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/main/java/com/ays/location/service/UserLocationService.java create mode 100644 src/main/java/com/ays/location/service/impl/UserLocationServiceImpl.java diff --git a/src/main/java/com/ays/location/service/UserLocationService.java b/src/main/java/com/ays/location/service/UserLocationService.java new file mode 100644 index 000000000..a7c2b2d16 --- /dev/null +++ b/src/main/java/com/ays/location/service/UserLocationService.java @@ -0,0 +1,18 @@ +package com.ays.location.service; + +import com.ays.location.model.dto.request.UserLocationSaveRequest; + +/** + * The UserLocationService interface provides methods to manage and store user location data. + * Implementing classes should define the behavior to save user location information. + */ +public interface UserLocationService { + + /** + * Saves the user's location based on the provided UserLocationSaveRequest. + * + * @param saveRequest The request containing the user's location information to be saved. + */ + void saveUserLocation(UserLocationSaveRequest saveRequest); + +} diff --git a/src/main/java/com/ays/location/service/impl/UserLocationServiceImpl.java b/src/main/java/com/ays/location/service/impl/UserLocationServiceImpl.java new file mode 100644 index 000000000..d53889950 --- /dev/null +++ b/src/main/java/com/ays/location/service/impl/UserLocationServiceImpl.java @@ -0,0 +1,49 @@ +package com.ays.location.service.impl; + +import com.ays.auth.model.AysIdentity; +import com.ays.location.model.dto.request.UserLocationSaveRequest; +import com.ays.location.model.entity.UserLocationEntity; +import com.ays.location.model.mapper.UserLocationSaveRequestToUserLocationEntityMapper; +import com.ays.location.repository.UserLocationRepository; +import com.ays.location.service.UserLocationService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +/** + * Implementation of the UserLocationService interface that manages and stores user location data. + * This service utilizes a repository to interact with the database for saving user location information. + */ +@Service +@RequiredArgsConstructor +class UserLocationServiceImpl implements UserLocationService { + + private final UserLocationRepository userLocationRepository; + + private final AysIdentity identity; + + + private final UserLocationSaveRequestToUserLocationEntityMapper userLocationSaveRequestToUserLocationEntityMapper = UserLocationSaveRequestToUserLocationEntityMapper.initialize(); + + /** + * Saves the user's location based on the provided UserLocationSaveRequest. + * If the user's location already exists in the database, updates the location; otherwise, creates a new entry. + * + * @param saveRequest The request containing the user's location information to be saved. + */ + @Override + public void saveUserLocation(final UserLocationSaveRequest saveRequest) { + userLocationRepository.findByUserId(identity.getUserId()) + .ifPresentOrElse( + userLocationEntityFromDatabase -> { + userLocationEntityFromDatabase.setPoint(saveRequest.getLatitude(), saveRequest.getLongitude()); + userLocationRepository.save(userLocationEntityFromDatabase); + }, + () -> { + final UserLocationEntity userLocationEntity = userLocationSaveRequestToUserLocationEntityMapper + .mapForSaving(saveRequest, identity.getUserId()); + userLocationRepository.save(userLocationEntity); + } + ); + } + +} From 91a49cb601bb9a3440197ebb885bf9ed5e9c349e Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Sat, 19 Aug 2023 18:36:18 +0300 Subject: [PATCH 07/21] Save Latest Location of User Endpoint Has Been Created in Controller Layer --- .../controller/UserLocationController.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 src/main/java/com/ays/location/controller/UserLocationController.java diff --git a/src/main/java/com/ays/location/controller/UserLocationController.java b/src/main/java/com/ays/location/controller/UserLocationController.java new file mode 100644 index 000000000..eda065964 --- /dev/null +++ b/src/main/java/com/ays/location/controller/UserLocationController.java @@ -0,0 +1,38 @@ +package com.ays.location.controller; + +import com.ays.common.model.dto.response.AysResponse; +import com.ays.location.model.dto.request.UserLocationSaveRequest; +import com.ays.location.service.UserLocationService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; +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; + +/** + * Controller class responsible for handling user location-related API endpoints. + * Provides endpoints for saving user location information. + */ +@RestController +@RequestMapping("/api/v1") +@RequiredArgsConstructor +class UserLocationController { + + private final UserLocationService userLocationService; + + /** + * Saves the user's location based on the provided UserLocationSaveRequest. + * + * @param saveRequest The request containing the user's location information to be saved. + * @return A response indicating the success of the operation. + */ + @PostMapping("/user/location") + @PreAuthorize("hasAnyAuthority('USER')") + public AysResponse saveUserLocation(@RequestBody @Valid final UserLocationSaveRequest saveRequest) { + userLocationService.saveUserLocation(saveRequest); + return AysResponse.SUCCESS; + } + +} From ea23fda285c8fe7efb14f4cbdc0adf55c5253ad0 Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Sat, 19 Aug 2023 18:37:26 +0300 Subject: [PATCH 08/21] `UserLocationSaveRequestBuilder` Class Has Been Created for Generating Mock Data --- .../UserLocationSaveRequestBuilder.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/test/java/com/ays/location/model/dto/request/UserLocationSaveRequestBuilder.java diff --git a/src/test/java/com/ays/location/model/dto/request/UserLocationSaveRequestBuilder.java b/src/test/java/com/ays/location/model/dto/request/UserLocationSaveRequestBuilder.java new file mode 100644 index 000000000..b30c3a807 --- /dev/null +++ b/src/test/java/com/ays/location/model/dto/request/UserLocationSaveRequestBuilder.java @@ -0,0 +1,27 @@ +package com.ays.location.model.dto.request; + +import com.ays.common.model.TestDataBuilder; + +public class UserLocationSaveRequestBuilder extends TestDataBuilder { + + public UserLocationSaveRequestBuilder() { + super(UserLocationSaveRequest.class); + } + + public UserLocationSaveRequestBuilder withValidFields() { + return this + .withLatitude(40.991739) + .withLongitude(29.024168); + } + + public UserLocationSaveRequestBuilder withLatitude(final Double latitude) { + data.setLatitude(latitude); + return this; + } + + public UserLocationSaveRequestBuilder withLongitude(final Double longitude) { + data.setLongitude(longitude); + return this; + } + +} From 2db3d81ae1eb31d1febd8903392152bb24237deb Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Sat, 19 Aug 2023 18:38:28 +0300 Subject: [PATCH 09/21] Save Latest Location of User Flow Has Been Covered with Controller Integration Tests --- .../UserLocationControllerTest.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/test/java/com/ays/location/controller/UserLocationControllerTest.java diff --git a/src/test/java/com/ays/location/controller/UserLocationControllerTest.java b/src/test/java/com/ays/location/controller/UserLocationControllerTest.java new file mode 100644 index 000000000..a2eeb045b --- /dev/null +++ b/src/test/java/com/ays/location/controller/UserLocationControllerTest.java @@ -0,0 +1,83 @@ +package com.ays.location.controller; + +import com.ays.AbstractRestControllerTest; +import com.ays.common.model.dto.response.AysResponse; +import com.ays.common.model.dto.response.AysResponseBuilder; +import com.ays.common.util.exception.model.AysError; +import com.ays.location.model.dto.request.UserLocationSaveRequest; +import com.ays.location.model.dto.request.UserLocationSaveRequestBuilder; +import com.ays.location.service.UserLocationService; +import com.ays.util.AysMockMvcRequestBuilders; +import com.ays.util.AysMockResultMatchersBuilders; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; + +class UserLocationControllerTest extends AbstractRestControllerTest { + + @MockBean + private UserLocationService userLocationService; + + + private static final String BASE_PATH = "/api/v1/user/location"; + + @Test + void givenValidUserLocationSaveRequest_whenSavedOrUpdatedLocation_thenReturnSuccess() throws Exception { + // Given + UserLocationSaveRequest mockUserLocationSaveRequest = new UserLocationSaveRequestBuilder() + .withValidFields() + .build(); + + // When + Mockito.doNothing().when(userLocationService).saveUserLocation(Mockito.any(UserLocationSaveRequest.class)); + + // Then + AysResponse mockAysResponse = AysResponse.SUCCESS; + mockMvc.perform(AysMockMvcRequestBuilders + .post(BASE_PATH, mockUserToken.getAccessToken(), mockUserLocationSaveRequest)) + .andDo(MockMvcResultHandlers.print()) + .andExpect(AysMockResultMatchersBuilders.status().isOk()) + .andExpect(AysMockResultMatchersBuilders.time() + .isNotEmpty()) + .andExpect(AysMockResultMatchersBuilders.httpStatus() + .value(mockAysResponse.getHttpStatus().getReasonPhrase())) + .andExpect(AysMockResultMatchersBuilders.isSuccess() + .value(mockAysResponse.getIsSuccess())) + .andExpect(AysMockResultMatchersBuilders.response() + .doesNotExist()); + + Mockito.verify(userLocationService, Mockito.times(1)) + .saveUserLocation(Mockito.any(UserLocationSaveRequest.class)); + } + + @Test + void givenValidUserSupportStatusUpdateRequest_whenAdminRole_thenReturnAccessDeniedException() throws Exception { + // Given + UserLocationSaveRequest mockUserLocationSaveRequest = new UserLocationSaveRequestBuilder() + .withValidFields() + .build(); + + // When + Mockito.doNothing().when(userLocationService).saveUserLocation(mockUserLocationSaveRequest); + + // Then + MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders + .post(BASE_PATH, mockAdminUserToken.getAccessToken(), mockUserLocationSaveRequest); + + AysResponse mockResponse = AysResponseBuilder.FORBIDDEN; + mockMvc.perform(mockHttpServletRequestBuilder) + .andDo(MockMvcResultHandlers.print()) + .andExpect(AysMockResultMatchersBuilders.status().isForbidden()) + .andExpect(AysMockResultMatchersBuilders.time() + .isNotEmpty()) + .andExpect(AysMockResultMatchersBuilders.httpStatus() + .value(mockResponse.getHttpStatus().name())) + .andExpect(AysMockResultMatchersBuilders.isSuccess() + .value(mockResponse.getIsSuccess())) + .andExpect(AysMockResultMatchersBuilders.response() + .doesNotExist()); + } + +} From 0fd843aa7f62d8d47265c65aceebac27a00d6a5d Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Sat, 19 Aug 2023 18:38:40 +0300 Subject: [PATCH 10/21] Save Latest Location of User Flow Has Been Covered with Unit Tests --- .../impl/UserLocationServiceImplTest.java | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java diff --git a/src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java b/src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java new file mode 100644 index 000000000..343a4e51c --- /dev/null +++ b/src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java @@ -0,0 +1,77 @@ +package com.ays.location.service.impl; + +import com.ays.AbstractUnitTest; +import com.ays.auth.model.AysIdentity; +import com.ays.common.util.AysRandomUtil; +import com.ays.location.model.dto.request.UserLocationSaveRequest; +import com.ays.location.model.dto.request.UserLocationSaveRequestBuilder; +import com.ays.location.model.entity.UserLocationEntity; +import com.ays.location.model.mapper.UserLocationSaveRequestToUserLocationEntityMapper; +import com.ays.location.repository.UserLocationRepository; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; + +import java.util.Optional; + +class UserLocationServiceImplTest extends AbstractUnitTest { + + @InjectMocks + private UserLocationServiceImpl userLocationService; + + @Mock + private UserLocationRepository userLocationRepository; + + @Mock + private AysIdentity identity; + + + private static final UserLocationSaveRequestToUserLocationEntityMapper USER_LOCATION_SAVE_REQUEST_TO_USER_LOCATION_ENTITY_MAPPER = UserLocationSaveRequestToUserLocationEntityMapper.initialize(); + + @Test + void givenValidUserLocationSaveRequest_whenUserLocationNotFound_thenSaveUserLastLocation() { + // Given + UserLocationSaveRequest mockSaveRequest = new UserLocationSaveRequestBuilder() + .withValidFields() + .build(); + String userId = AysRandomUtil.generateUUID(); + + // When + Mockito.when(identity.getUserId()).thenReturn(userId); + + UserLocationEntity userLocationEntity = USER_LOCATION_SAVE_REQUEST_TO_USER_LOCATION_ENTITY_MAPPER + .mapForSaving(mockSaveRequest, userId); + Mockito.when(userLocationRepository.findByUserId(userId)) + .thenReturn(Optional.of(userLocationEntity)); + + // Then + userLocationService.saveUserLocation(mockSaveRequest); + + Mockito.verify(userLocationRepository, Mockito.times(1)) + .findByUserId(Mockito.anyString()); + Mockito.verify(userLocationRepository, Mockito.times(1)) + .save(Mockito.any(UserLocationEntity.class)); + } + + @Test + void givenValidUserLocationSaveRequest_whenUserLocationNotFound_thenUpdateUserLastLocation() { + // Given + UserLocationSaveRequest mockSaveRequest = new UserLocationSaveRequestBuilder() + .withValidFields() + .build(); + String userId = AysRandomUtil.generateUUID(); + + // When + Mockito.when(identity.getUserId()).thenReturn(userId); + + // Then + userLocationService.saveUserLocation(mockSaveRequest); + + Mockito.verify(userLocationRepository, Mockito.times(1)) + .findByUserId(Mockito.anyString()); + Mockito.verify(userLocationRepository, Mockito.times(1)) + .save(Mockito.any(UserLocationEntity.class)); + } + +} \ No newline at end of file From 67a22a6662b6dca3c6c377d71ccf5a1b1b041764 Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Sat, 19 Aug 2023 18:38:47 +0300 Subject: [PATCH 11/21] Save Latest Location of User Flow Has Been Covered with System Tests --- .../controller/UserLocationSystemTest.java | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/test/java/com/ays/location/controller/UserLocationSystemTest.java diff --git a/src/test/java/com/ays/location/controller/UserLocationSystemTest.java b/src/test/java/com/ays/location/controller/UserLocationSystemTest.java new file mode 100644 index 000000000..ace81a486 --- /dev/null +++ b/src/test/java/com/ays/location/controller/UserLocationSystemTest.java @@ -0,0 +1,68 @@ +package com.ays.location.controller; + +import com.ays.AbstractSystemTest; +import com.ays.common.model.dto.response.AysResponse; +import com.ays.common.model.dto.response.AysResponseBuilder; +import com.ays.common.util.exception.model.AysError; +import com.ays.location.model.dto.request.UserLocationSaveRequest; +import com.ays.location.model.dto.request.UserLocationSaveRequestBuilder; +import com.ays.util.AysMockMvcRequestBuilders; +import com.ays.util.AysMockResultMatchersBuilders; +import org.junit.jupiter.api.Test; +import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; + +class UserLocationSystemTest extends AbstractSystemTest { + + + private static final String BASE_PATH = "/api/v1/user/location"; + + @Test + void givenValidUserLocationSaveRequest_whenSavedOrUpdatedLocation_thenReturnSuccess() throws Exception { + // Given + UserLocationSaveRequest mockUserLocationSaveRequest = new UserLocationSaveRequestBuilder() + .withValidFields() + .build(); + + // Then + AysResponse mockAysResponse = AysResponse.SUCCESS; + mockMvc.perform(AysMockMvcRequestBuilders + .post(BASE_PATH, userTokenOne.getAccessToken(), mockUserLocationSaveRequest)) + .andDo(MockMvcResultHandlers.print()) + .andExpect(AysMockResultMatchersBuilders.status().isOk()) + .andExpect(AysMockResultMatchersBuilders.time() + .isNotEmpty()) + .andExpect(AysMockResultMatchersBuilders.httpStatus() + .value(mockAysResponse.getHttpStatus().getReasonPhrase())) + .andExpect(AysMockResultMatchersBuilders.isSuccess() + .value(mockAysResponse.getIsSuccess())) + .andExpect(AysMockResultMatchersBuilders.response() + .doesNotExist()); + } + + @Test + void givenValidUserSupportStatusUpdateRequest_whenAdminRole_thenReturnAccessDeniedException() throws Exception { + // Given + UserLocationSaveRequest mockUserLocationSaveRequest = new UserLocationSaveRequestBuilder() + .withValidFields() + .build(); + + // Then + MockHttpServletRequestBuilder mockHttpServletRequestBuilder = AysMockMvcRequestBuilders + .post(BASE_PATH, adminUserTokenOne.getAccessToken(), mockUserLocationSaveRequest); + + AysResponse mockResponse = AysResponseBuilder.FORBIDDEN; + mockMvc.perform(mockHttpServletRequestBuilder) + .andDo(MockMvcResultHandlers.print()) + .andExpect(AysMockResultMatchersBuilders.status().isForbidden()) + .andExpect(AysMockResultMatchersBuilders.time() + .isNotEmpty()) + .andExpect(AysMockResultMatchersBuilders.httpStatus() + .value(mockResponse.getHttpStatus().name())) + .andExpect(AysMockResultMatchersBuilders.isSuccess() + .value(mockResponse.getIsSuccess())) + .andExpect(AysMockResultMatchersBuilders.response() + .doesNotExist()); + } + +} From 3a5615933c4d5978604643b6372fa7693e187d75 Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Sun, 20 Aug 2023 23:58:07 +0300 Subject: [PATCH 12/21] `point()` Method Has Been Override on Default Lombok Builder Pattern & Method Has Been Used --- .../com/ays/location/model/entity/UserLocationEntity.java | 7 +++++++ .../UserLocationSaveRequestToUserLocationEntityMapper.java | 5 ++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ays/location/model/entity/UserLocationEntity.java b/src/main/java/com/ays/location/model/entity/UserLocationEntity.java index cb2be3a6e..e833551b4 100644 --- a/src/main/java/com/ays/location/model/entity/UserLocationEntity.java +++ b/src/main/java/com/ays/location/model/entity/UserLocationEntity.java @@ -43,4 +43,11 @@ public void setPoint(final Double latitude, final Double longitude) { this.point = AysLocationUtil.generatePoint(latitude, longitude); } + public abstract static class UserLocationEntityBuilder> extends BaseEntity.BaseEntityBuilder { + public B point(final Double latitude, final Double longitude) { + this.point = AysLocationUtil.generatePoint(latitude, longitude); + return this.self(); + } + } + } diff --git a/src/main/java/com/ays/location/model/mapper/UserLocationSaveRequestToUserLocationEntityMapper.java b/src/main/java/com/ays/location/model/mapper/UserLocationSaveRequestToUserLocationEntityMapper.java index 45d5dfab2..01cd748e9 100644 --- a/src/main/java/com/ays/location/model/mapper/UserLocationSaveRequestToUserLocationEntityMapper.java +++ b/src/main/java/com/ays/location/model/mapper/UserLocationSaveRequestToUserLocationEntityMapper.java @@ -24,11 +24,10 @@ public interface UserLocationSaveRequestToUserLocationEntityMapper extends BaseM * @return the mapped {@link UserLocationEntity} object. */ default UserLocationEntity mapForSaving(UserLocationSaveRequest saveRequest, String userId) { - final UserLocationEntity userLocationEntity = UserLocationEntity.builder() + return UserLocationEntity.builder() .userId(userId) + .point(saveRequest.getLatitude(), saveRequest.getLongitude()) .build(); - userLocationEntity.setPoint(saveRequest.getLatitude(), saveRequest.getLongitude()); - return userLocationEntity; } /** From c8236cbcada49a1073193a1f9cbc8139806cb33f Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Tue, 22 Aug 2023 18:56:19 +0300 Subject: [PATCH 13/21] Terminal Commands Have Been Updated for Running Database on Docker --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 742b36b59..787d2ccb7 100644 --- a/README.md +++ b/README.md @@ -126,19 +126,19 @@ First of all, generate personal access token with this url : https://github.com/ Before running the project, you need to run the following command to start the MySQL container: ``` -docker compose up -d --build mysql +docker compose up -d --build database ``` If you want to recreate the MySQL container, you can run the following command: ``` -docker compose up --force-recreate -d --build mysql +docker compose up --force-recreate -d --build database ``` If you want to stop the MySQL container, you can run the following command: ``` -docker compose down -v mysql +docker compose down -v database ``` --- From 975e742e2e6b3a494a07e6efd1bc2d3eb529f53e Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Tue, 22 Aug 2023 19:06:17 +0300 Subject: [PATCH 14/21] Duplicated `AysLocationUtil` Has Been Removed --- .../model/entity/AssignmentEntity.java | 2 +- .../com/ays/common/util/AysLocationUtil.java | 28 ------------------- 2 files changed, 1 insertion(+), 29 deletions(-) delete mode 100644 src/main/java/com/ays/common/util/AysLocationUtil.java diff --git a/src/main/java/com/ays/assignment/model/entity/AssignmentEntity.java b/src/main/java/com/ays/assignment/model/entity/AssignmentEntity.java index d1ae8afd9..c1f9041b7 100644 --- a/src/main/java/com/ays/assignment/model/entity/AssignmentEntity.java +++ b/src/main/java/com/ays/assignment/model/entity/AssignmentEntity.java @@ -2,8 +2,8 @@ import com.ays.assignment.model.enums.AssignmentStatus; import com.ays.common.model.entity.BaseEntity; -import com.ays.common.util.AysLocationUtil; import com.ays.institution.model.entity.InstitutionEntity; +import com.ays.location.util.AysLocationUtil; import com.ays.user.model.entity.UserEntity; import jakarta.persistence.*; import lombok.AllArgsConstructor; diff --git a/src/main/java/com/ays/common/util/AysLocationUtil.java b/src/main/java/com/ays/common/util/AysLocationUtil.java deleted file mode 100644 index c618bb882..000000000 --- a/src/main/java/com/ays/common/util/AysLocationUtil.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.ays.common.util; - -import lombok.experimental.UtilityClass; -import org.locationtech.jts.geom.*; -import org.locationtech.jts.geom.impl.CoordinateArraySequence; - -/** - * Utility class for handling location-related operations. - * Provides methods to generate geometric points based on latitude and longitude coordinates. - */ -@UtilityClass -public class AysLocationUtil { - - /** - * Generates a Point object representing a location based on the provided latitude and longitude coordinates. - * - * @param latitude The latitude coordinate of the location. - * @param longitude The longitude coordinate of the location. - * @return A Point object representing the location. - */ - public static Point generatePoint(final Double latitude, final Double longitude) { - final Coordinate[] coordinates = new Coordinate[]{new Coordinate(latitude, longitude)}; - final CoordinateSequence coordinateSequence = new CoordinateArraySequence(coordinates); - final PrecisionModel precisionModel = new PrecisionModel(PrecisionModel.FLOATING); - return new GeometryFactory(precisionModel, 4326).createPoint(coordinateSequence); - } - -} From 404e922641384425f026eb334a8a10cd1679bffa Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Tue, 22 Aug 2023 20:10:59 +0300 Subject: [PATCH 15/21] `AysUserLocationCannotBeUpdatedException` Class Has Been Created --- ...sUserLocationCannotBeUpdatedException.java | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/main/java/com/ays/location/util/exception/AysUserLocationCannotBeUpdatedException.java diff --git a/src/main/java/com/ays/location/util/exception/AysUserLocationCannotBeUpdatedException.java b/src/main/java/com/ays/location/util/exception/AysUserLocationCannotBeUpdatedException.java new file mode 100644 index 000000000..1de4fe0bb --- /dev/null +++ b/src/main/java/com/ays/location/util/exception/AysUserLocationCannotBeUpdatedException.java @@ -0,0 +1,33 @@ +package com.ays.location.util.exception; + +import com.ays.common.util.exception.AysProcessException; + +import java.io.Serial; + +/** + * This exception is thrown when a user's location cannot be updated. Reasons for not being able to update the user's + * location may include the absence of an assigned task or the assigned task not being in progress status. + *

+ * This exception is typically derived from the {@link AysProcessException} class and represents a specific process state + * or condition. + * + * @see AysProcessException + */ +public class AysUserLocationCannotBeUpdatedException extends AysProcessException { + + /** + * A special field containing version information along with the serial number. + */ + @Serial + private static final long serialVersionUID = 2733712280590701217L; + + /** + * Constructs an exception for the specified identifier (id). + * + * @param id The identifier (id) that describes the reason for the unupdatable user location. + */ + public AysUserLocationCannotBeUpdatedException() { + super("USER LOCATION CANNOT BE UPDATED BECAUSE ASSIGNMENT NOT EXIST OR NOT IN PROGRESS STATUS!"); + } + +} From 30ebf75877cbec007510b15a74e7da47fffee170 Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Tue, 22 Aug 2023 20:19:49 +0300 Subject: [PATCH 16/21] `isAssignmentInProgress` Check Has Been Added to User Location Save Flow --- .../assignment/repository/AssignmentRepository.java | 8 ++++++++ .../service/impl/UserLocationServiceImpl.java | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/main/java/com/ays/assignment/repository/AssignmentRepository.java b/src/main/java/com/ays/assignment/repository/AssignmentRepository.java index 7f885974c..8d36b544e 100644 --- a/src/main/java/com/ays/assignment/repository/AssignmentRepository.java +++ b/src/main/java/com/ays/assignment/repository/AssignmentRepository.java @@ -1,6 +1,7 @@ package com.ays.assignment.repository; import com.ays.assignment.model.entity.AssignmentEntity; +import com.ays.assignment.model.enums.AssignmentStatus; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; @@ -9,5 +10,12 @@ */ public interface AssignmentRepository extends JpaRepository, JpaSpecificationExecutor { + /** + * Checks whether an assignment exists for a specific user ID. + * + * @param userId The ID of the user to check the assignment for. + * @return {@code true} if an assignment exists for the specified user ID, otherwise {@code false}. + */ + boolean existsByUserIdAndStatus(String userId, AssignmentStatus status); } diff --git a/src/main/java/com/ays/location/service/impl/UserLocationServiceImpl.java b/src/main/java/com/ays/location/service/impl/UserLocationServiceImpl.java index d53889950..a7d3d5b48 100644 --- a/src/main/java/com/ays/location/service/impl/UserLocationServiceImpl.java +++ b/src/main/java/com/ays/location/service/impl/UserLocationServiceImpl.java @@ -1,11 +1,14 @@ package com.ays.location.service.impl; +import com.ays.assignment.model.enums.AssignmentStatus; +import com.ays.assignment.repository.AssignmentRepository; import com.ays.auth.model.AysIdentity; import com.ays.location.model.dto.request.UserLocationSaveRequest; import com.ays.location.model.entity.UserLocationEntity; import com.ays.location.model.mapper.UserLocationSaveRequestToUserLocationEntityMapper; import com.ays.location.repository.UserLocationRepository; import com.ays.location.service.UserLocationService; +import com.ays.location.util.exception.AysUserLocationCannotBeUpdatedException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -18,6 +21,7 @@ class UserLocationServiceImpl implements UserLocationService { private final UserLocationRepository userLocationRepository; + private final AssignmentRepository assignmentRepository; private final AysIdentity identity; @@ -32,6 +36,13 @@ class UserLocationServiceImpl implements UserLocationService { */ @Override public void saveUserLocation(final UserLocationSaveRequest saveRequest) { + + final boolean isAssignmentInProgress = assignmentRepository + .existsByUserIdAndStatus(identity.getUserId(), AssignmentStatus.IN_PROGRESS); + if (!isAssignmentInProgress) { + throw new AysUserLocationCannotBeUpdatedException(); + } + userLocationRepository.findByUserId(identity.getUserId()) .ifPresentOrElse( userLocationEntityFromDatabase -> { From f129b8de18064f12898466a47c0765a7e8871271 Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Tue, 22 Aug 2023 20:20:22 +0300 Subject: [PATCH 17/21] Mock Assignment DMLs Have Been Fixed and New Mock Assignment DML Has Been Added --- .../db/changelog/changes/5-ays-dml.xml | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/resources/db/changelog/changes/5-ays-dml.xml b/src/main/resources/db/changelog/changes/5-ays-dml.xml index 61d8b1c80..fc084a668 100644 --- a/src/main/resources/db/changelog/changes/5-ays-dml.xml +++ b/src/main/resources/db/changelog/changes/5-ays-dml.xml @@ -25,22 +25,23 @@ INSERT INTO AYS_ASSIGNMENT (ID, INSTITUTION_ID, DESCRIPTION, FIRST_NAME, LAST_NAME, COUNTRY_CODE, - LINE_NUMBER, STATUS, - POINT, CREATED_USER, CREATED_AT) + LINE_NUMBER, POINT, STATUS, CREATED_USER, CREATED_AT) VALUES ('3b30cac9-0645-48cb-bc98-2e928df521ab', '77ece256-bf0e-4bbe-801d-173083f8bdcf', - '100L İçme Suyu İhtiyacı', - 'Ahmet', 'Mehmet', '90', '1234567890', 'AVAILABLE', - ST_GeomFromText('POINT(40.981210 29.026083)', 4326), - 'AYS', CURRENT_TIMESTAMP); + '100L İçme Suyu İhtiyacı', 'Ahmet', 'Mehmet', '90', '1234567890', + ST_GeomFromText('POINT(40.981210 29.026083)', 4326), 'AVAILABLE', 'AYS', CURRENT_TIMESTAMP); INSERT INTO AYS_ASSIGNMENT (ID, INSTITUTION_ID, DESCRIPTION, FIRST_NAME, LAST_NAME, COUNTRY_CODE, - LINE_NUMBER, STATUS, - POINT, CREATED_USER, CREATED_AT) - VALUES ('a9ec051e-3c4f-4cb5-ab08-e9dcee5e1f03', '91df7ae9-d5b9-44ae-b54f-d5d55359c4a4', 'Kıyafet İhtiyacı', - 'Cem', 'Orkun', '90', '1234567890', 'AVAILABLE', - ST_GeomFromText('POINT(40.981210 29.000000)', 4326), - 'AYS', CURRENT_TIMESTAMP); + LINE_NUMBER, POINT, STATUS, CREATED_USER, CREATED_AT) + VALUES ('a9ec051e-3c4f-4cb5-ab08-e9dcee5e1f03', '91df7ae9-d5b9-44ae-b54f-d5d55359c4a4', + 'Kıyafet İhtiyacı', 'Cem', 'Orkun', '90', '1234567890', + ST_GeomFromText('POINT(40.981210 29.000000)', 4326), 'AVAILABLE', 'AYS', CURRENT_TIMESTAMP); + INSERT INTO AYS_ASSIGNMENT (ID, USER_ID, INSTITUTION_ID, DESCRIPTION, FIRST_NAME, LAST_NAME, COUNTRY_CODE, + LINE_NUMBER, POINT, STATUS, CREATED_USER, CREATED_AT) + VALUES ('823835f4-85f0-4052-a09c-b9b6e5284afc', 'edb36891-b898-4c12-bcec-d9aaa5d45190', + '91df7ae9-d5b9-44ae-b54f-d5d55359c4a4', 'Kıyafet İhtiyacı', 'Cem', 'Orkun', + '90', '1234567890', ST_GeomFromText('POINT(40.981210 29.000000)', 4326), + 'IN_PROGRESS', 'AYS', CURRENT_TIMESTAMP); From bb76d1b743c3661a24d9da7be8a24189cb722a9f Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Tue, 22 Aug 2023 20:20:49 +0300 Subject: [PATCH 18/21] `givenValidUserLocationSaveRequest_whenSavedOrUpdatedLocation_thenReturnSuccess()` Test Has Been Fixed in `UserLocationSystemTest` Class --- .../com/ays/location/controller/UserLocationSystemTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/ays/location/controller/UserLocationSystemTest.java b/src/test/java/com/ays/location/controller/UserLocationSystemTest.java index ace81a486..923bd419e 100644 --- a/src/test/java/com/ays/location/controller/UserLocationSystemTest.java +++ b/src/test/java/com/ays/location/controller/UserLocationSystemTest.java @@ -27,7 +27,7 @@ void givenValidUserLocationSaveRequest_whenSavedOrUpdatedLocation_thenReturnSucc // Then AysResponse mockAysResponse = AysResponse.SUCCESS; mockMvc.perform(AysMockMvcRequestBuilders - .post(BASE_PATH, userTokenOne.getAccessToken(), mockUserLocationSaveRequest)) + .post(BASE_PATH, userTokenThree.getAccessToken(), mockUserLocationSaveRequest)) .andDo(MockMvcResultHandlers.print()) .andExpect(AysMockResultMatchersBuilders.status().isOk()) .andExpect(AysMockResultMatchersBuilders.time() From 3e623707c7010650f18d79520f3ec82fe25e667b Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Tue, 22 Aug 2023 20:21:28 +0300 Subject: [PATCH 19/21] `isAssignmentInProgress` Check Has Been Added to `givenValidUserLocationSaveRequest_whenUserLocationNotFound_thenSaveUserLastLocation` Test in `UserLocationServiceImplTest` Class --- .../service/impl/UserLocationServiceImplTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java b/src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java index 343a4e51c..58b2f540c 100644 --- a/src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java +++ b/src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java @@ -1,6 +1,8 @@ package com.ays.location.service.impl; import com.ays.AbstractUnitTest; +import com.ays.assignment.model.enums.AssignmentStatus; +import com.ays.assignment.repository.AssignmentRepository; import com.ays.auth.model.AysIdentity; import com.ays.common.util.AysRandomUtil; import com.ays.location.model.dto.request.UserLocationSaveRequest; @@ -8,6 +10,8 @@ import com.ays.location.model.entity.UserLocationEntity; import com.ays.location.model.mapper.UserLocationSaveRequestToUserLocationEntityMapper; import com.ays.location.repository.UserLocationRepository; +import com.ays.location.util.exception.AysUserLocationCannotBeUpdatedException; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; @@ -23,6 +27,9 @@ class UserLocationServiceImplTest extends AbstractUnitTest { @Mock private UserLocationRepository userLocationRepository; + @Mock + private AssignmentRepository assignmentRepository; + @Mock private AysIdentity identity; @@ -40,6 +47,9 @@ void givenValidUserLocationSaveRequest_whenUserLocationNotFound_thenSaveUserLast // When Mockito.when(identity.getUserId()).thenReturn(userId); + Mockito.when(assignmentRepository.existsByUserIdAndStatus(userId, AssignmentStatus.IN_PROGRESS)) + .thenReturn(true); + UserLocationEntity userLocationEntity = USER_LOCATION_SAVE_REQUEST_TO_USER_LOCATION_ENTITY_MAPPER .mapForSaving(mockSaveRequest, userId); Mockito.when(userLocationRepository.findByUserId(userId)) @@ -48,6 +58,8 @@ void givenValidUserLocationSaveRequest_whenUserLocationNotFound_thenSaveUserLast // Then userLocationService.saveUserLocation(mockSaveRequest); + Mockito.verify(assignmentRepository, Mockito.times(1)) + .existsByUserIdAndStatus(Mockito.anyString(), Mockito.any(AssignmentStatus.class)); Mockito.verify(userLocationRepository, Mockito.times(1)) .findByUserId(Mockito.anyString()); Mockito.verify(userLocationRepository, Mockito.times(1)) From 3e269e9949af89094bbd7345a50c3c9f5f6160d8 Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Tue, 22 Aug 2023 20:21:45 +0300 Subject: [PATCH 20/21] `isAssignmentInProgress` Check Has Been Added to `givenValidUserLocationSaveRequest_whenUserLocationNotFound_thenUpdateUserLastLocation` Test in `UserLocationServiceImplTest` Class --- .../location/service/impl/UserLocationServiceImplTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java b/src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java index 58b2f540c..1963befb6 100644 --- a/src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java +++ b/src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java @@ -77,9 +77,14 @@ void givenValidUserLocationSaveRequest_whenUserLocationNotFound_thenUpdateUserLa // When Mockito.when(identity.getUserId()).thenReturn(userId); + Mockito.when(assignmentRepository.existsByUserIdAndStatus(userId, AssignmentStatus.IN_PROGRESS)) + .thenReturn(true); + // Then userLocationService.saveUserLocation(mockSaveRequest); + Mockito.verify(assignmentRepository, Mockito.times(1)) + .existsByUserIdAndStatus(Mockito.anyString(), Mockito.any(AssignmentStatus.class)); Mockito.verify(userLocationRepository, Mockito.times(1)) .findByUserId(Mockito.anyString()); Mockito.verify(userLocationRepository, Mockito.times(1)) From 74d1fff78f280463d623d90759e4f52883e8b977 Mon Sep 17 00:00:00 2001 From: Agit Rubar Demir Date: Tue, 22 Aug 2023 20:22:09 +0300 Subject: [PATCH 21/21] `givenValidUserLocationSaveRequest_whenAssignmentNotFoundOrNotInProgress_thenThrowAysUserLocationCannotBeUpdatedException` Test Has Been Created in `UserLocationServiceImplTest` Class --- .../impl/UserLocationServiceImplTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java b/src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java index 1963befb6..156ada202 100644 --- a/src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java +++ b/src/test/java/com/ays/location/service/impl/UserLocationServiceImplTest.java @@ -66,6 +66,34 @@ void givenValidUserLocationSaveRequest_whenUserLocationNotFound_thenSaveUserLast .save(Mockito.any(UserLocationEntity.class)); } + @Test + void givenValidUserLocationSaveRequest_whenAssignmentNotFoundOrNotInProgress_thenThrowAysUserLocationCannotBeUpdatedException() { + // Given + UserLocationSaveRequest mockSaveRequest = new UserLocationSaveRequestBuilder() + .withValidFields() + .build(); + String userId = AysRandomUtil.generateUUID(); + + // When + Mockito.when(identity.getUserId()).thenReturn(userId); + + Mockito.when(assignmentRepository.existsByUserIdAndStatus(userId, AssignmentStatus.IN_PROGRESS)) + .thenReturn(false); + + // Then + Assertions.assertThrows( + AysUserLocationCannotBeUpdatedException.class, + () -> userLocationService.saveUserLocation(mockSaveRequest) + ); + + Mockito.verify(assignmentRepository, Mockito.times(1)) + .existsByUserIdAndStatus(Mockito.anyString(), Mockito.any(AssignmentStatus.class)); + Mockito.verify(userLocationRepository, Mockito.times(0)) + .findByUserId(Mockito.anyString()); + Mockito.verify(userLocationRepository, Mockito.times(0)) + .save(Mockito.any(UserLocationEntity.class)); + } + @Test void givenValidUserLocationSaveRequest_whenUserLocationNotFound_thenUpdateUserLastLocation() { // Given