Skip to content

Commit

Permalink
Task 36 : Define Custom Annotation named TimestampAfterStoreCreation …
Browse files Browse the repository at this point in the history
…and Revise relevant classes with respect to it
  • Loading branch information
Rapter1990 committed Sep 29, 2024
1 parent ca5522c commit 87e3a08
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.casestudy.migroscouriertracking.courier.model.dto.request;

import com.casestudy.migroscouriertracking.courier.utils.validator.TimestampAfterStoreCreation;
import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.*;
import lombok.*;
Expand All @@ -14,6 +15,7 @@
@NoArgsConstructor
@AllArgsConstructor
@Builder
@TimestampAfterStoreCreation(message = "Timestamp must be after the nearest store's creation time")
public class LogCourierLocationRequest {

@NotBlank
Expand All @@ -29,7 +31,6 @@ public class LogCourierLocationRequest {
private Double lng;

@JsonFormat(pattern = "dd/MM/yyyy HH:mm")
@FutureOrPresent(message = "Timestamp must be after the store creation time")
private LocalDateTime timestamp;

}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.casestudy.migroscouriertracking.courier.utils.validator;

import jakarta.validation.Constraint;
import jakarta.validation.Payload;

import java.lang.annotation.*;

@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = TimestampAfterStoreCreationValidator.class)
@Documented
public @interface TimestampAfterStoreCreation {
String message() default "Timestamp must be after the store creation time";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.casestudy.migroscouriertracking.courier.utils.validator;

import com.casestudy.migroscouriertracking.courier.model.dto.request.LogCourierLocationRequest;
import com.casestudy.migroscouriertracking.courier.model.entity.StoreEntity;
import com.casestudy.migroscouriertracking.courier.repository.StoreRepository;
import com.casestudy.migroscouriertracking.courier.utils.DistanceUtils;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import lombok.RequiredArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@RequiredArgsConstructor
public class TimestampAfterStoreCreationValidator implements ConstraintValidator<TimestampAfterStoreCreation, LogCourierLocationRequest> {

private final StoreRepository storeRepository;

@Override
public void initialize(TimestampAfterStoreCreation constraintAnnotation) {
}

@Override
public boolean isValid(LogCourierLocationRequest request, ConstraintValidatorContext context) {
double lat = request.getLat();
double lng = request.getLng();
LocalDateTime timestamp = request.getTimestamp();


// Find the first store within 100 meters radius of the courier's location
Optional<StoreEntity> nearestStore = storeRepository.findAll().stream()
.filter(store -> DistanceUtils.isWithinRadius(lat, lng, store.getLat(), store.getLng(), 100.0))
.findFirst();

// If a nearby store is found, validate the timestamp
return nearestStore.map(store -> timestamp.isAfter(store.getCreatedAt()))
.orElse(false); // No nearby store found, validation fails

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import com.casestudy.migroscouriertracking.courier.model.dto.request.LogCourierLocationRequest;
import com.casestudy.migroscouriertracking.courier.model.dto.request.TravelQueryRequest;
import com.casestudy.migroscouriertracking.courier.model.dto.response.CourierResponse;
import com.casestudy.migroscouriertracking.courier.model.entity.StoreEntity;
import com.casestudy.migroscouriertracking.courier.model.mapper.CourierToCourierResponseMapper;
import com.casestudy.migroscouriertracking.courier.repository.StoreRepository;
import com.casestudy.migroscouriertracking.courier.service.CourierService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
Expand All @@ -32,6 +34,9 @@ class CourierControllerTest extends AbstractRestControllerTest {
@MockBean
private CourierService courierService;

@MockBean
private StoreRepository storeRepository;

private final CourierToCourierResponseMapper courierToCourierResponseMapper = CourierToCourierResponseMapper.initialize();

@Test
Expand All @@ -45,7 +50,15 @@ public void logCourierLocation_shouldReturnSuccessMessage() throws Exception {
.timestamp(LocalDateTime.now().plusMinutes(1))
.build();

// Mock nearest store's createdAt time to be before the logRequest's timestamp
StoreEntity mockStore = StoreEntity.builder()
.lat(37.7749)
.lng(-122.4194)
.createdAt(LocalDateTime.now().minusDays(1))
.build();

// When
when(storeRepository.findAll()).thenReturn(List.of(mockStore));
doNothing().when(courierService).logCourierLocation(any());

// Then
Expand Down

0 comments on commit 87e3a08

Please sign in to comment.