diff --git a/application/src/main/java/com/techivw/webprice/application/ports/out/PriceRepositoryPort.java b/application/src/main/java/com/techivw/webprice/application/ports/out/PriceRepositoryPort.java index 6e75ca5..6cf9c6b 100644 --- a/application/src/main/java/com/techivw/webprice/application/ports/out/PriceRepositoryPort.java +++ b/application/src/main/java/com/techivw/webprice/application/ports/out/PriceRepositoryPort.java @@ -2,9 +2,10 @@ package com.techivw.webprice.application.ports.out; import com.techivw.webprice.domain.Price; +import java.time.LocalDateTime; import java.util.List; public interface PriceRepositoryPort { - List findPricesByProductIdAndBrandId(Long productId, Long brandId); + List findPricesByProductIdAndBrandIdAndDateTimeBetween(Long productId, Long brandId, LocalDateTime dateTime); } diff --git a/application/src/main/java/com/techivw/webprice/application/services/PriceService.java b/application/src/main/java/com/techivw/webprice/application/services/PriceService.java index ae5ae4d..22ab8ef 100644 --- a/application/src/main/java/com/techivw/webprice/application/services/PriceService.java +++ b/application/src/main/java/com/techivw/webprice/application/services/PriceService.java @@ -21,14 +21,12 @@ public class PriceService implements PriceServicePort { @Override public Price getPriceWithHighestPriorityByDateTimeAndProductIdAndBrandId(LocalDateTime dateTime, Long productId, Long brandId) { - List prices = priceRepositoryPort.findPricesByProductIdAndBrandId(productId, brandId); + List prices = priceRepositoryPort.findPricesByProductIdAndBrandIdAndDateTimeBetween(productId, brandId, dateTime); - Optional maxPriorityPrice = prices.stream() - .filter(price -> !dateTime.isBefore(price.getStartDate()) && !dateTime.isAfter(price.getEndDate())) - .max(Comparator.comparing(Price::getPriority)); - - return maxPriorityPrice.orElseThrow(() -> - new NotFoundException(String.format( - "Price for product %d of brand %d not found for date %s", productId, brandId, dateTime))); + return prices.stream() + .max(Comparator.comparing(Price::getPriority)) + .orElseThrow(() -> new NotFoundException( + String.format("Price for product %d of brand %d not found for date %s", + productId, brandId, dateTime))); } } diff --git a/application/src/test/java/com/techivw/webprice/application/services/PriceServiceTest.java b/application/src/test/java/com/techivw/webprice/application/services/PriceServiceTest.java index 7952aa7..b5fb724 100644 --- a/application/src/test/java/com/techivw/webprice/application/services/PriceServiceTest.java +++ b/application/src/test/java/com/techivw/webprice/application/services/PriceServiceTest.java @@ -29,7 +29,7 @@ class PriceServiceTest { private PriceServicePort priceService; - private final LocalDateTime TEST_DATE = LocalDateTime.parse("2023-01-01T12:00:00"); + private final LocalDateTime TEST_DATE = LocalDateTime.parse("2020-06-14T16:00:00"); private final Long TEST_PRODUCT_ID = 35455L; private final Long TEST_BRAND_ID = 1L; @@ -44,8 +44,8 @@ class PriceServiceTest { Price highPriorityPrice = createPrice(2); List prices = Arrays.asList(lowPriorityPrice, highPriorityPrice); - when(priceRepositoryPort.findPricesByProductIdAndBrandId( - eq(TEST_PRODUCT_ID), eq(TEST_BRAND_ID))) + when(priceRepositoryPort.findPricesByProductIdAndBrandIdAndDateTimeBetween( + eq(TEST_PRODUCT_ID), eq(TEST_BRAND_ID), eq(TEST_DATE))) .thenReturn(prices); Price result = priceService.getPriceWithHighestPriorityByDateTimeAndProductIdAndBrandId( @@ -57,8 +57,8 @@ class PriceServiceTest { @Test void shouldThrowNotFoundExceptionWhenPriceListIsEmpty() { - when(priceRepositoryPort.findPricesByProductIdAndBrandId( - eq(TEST_PRODUCT_ID), eq(TEST_BRAND_ID))) + when(priceRepositoryPort.findPricesByProductIdAndBrandIdAndDateTimeBetween( + eq(TEST_PRODUCT_ID), eq(TEST_BRAND_ID), eq(TEST_DATE))) .thenReturn(Collections.emptyList()); assertThrows(NotFoundException.class, () -> @@ -66,28 +66,6 @@ class PriceServiceTest { TEST_DATE, TEST_PRODUCT_ID, TEST_BRAND_ID)); } - @Test - void shouldThrowNotFoundExceptionWhenNoPriceInDateRange() { - Price price = Price.builder() - .brandId(TEST_BRAND_ID) - .productId(TEST_PRODUCT_ID) - .startDate(TEST_DATE.plusDays(1)) - .endDate(TEST_DATE.plusDays(2)) - .priceList(1L) - .price(BigDecimal.valueOf(35.50)) - .priority(1) - .currency("EUR") - .build(); - - when(priceRepositoryPort.findPricesByProductIdAndBrandId( - eq(TEST_PRODUCT_ID), eq(TEST_BRAND_ID))) - .thenReturn(Collections.singletonList(price)); - - assertThrows(NotFoundException.class, () -> - priceService.getPriceWithHighestPriorityByDateTimeAndProductIdAndBrandId( - TEST_DATE, TEST_PRODUCT_ID, TEST_BRAND_ID)); - } - private Price createPrice(int priority) { return Price.builder() .brandId(TEST_BRAND_ID) @@ -100,4 +78,4 @@ class PriceServiceTest { .currency("EUR") .build(); } -} \ No newline at end of file +} diff --git a/infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/adapters/PriceControllerAdapter.java b/infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/adapters/PriceControllerAdapter.java index f790640..383668b 100644 --- a/infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/adapters/PriceControllerAdapter.java +++ b/infrastructure/in/rest-api/src/main/java/com/techivw/webprice/infrastructure/in/controllers/adapters/PriceControllerAdapter.java @@ -39,7 +39,7 @@ public class PriceControllerAdapter { @ApiResponse(responseCode = "400", description = "Invalid request parameters") @ApiResponse(responseCode = "404", description = "Price information not found for the given parameters") public ResponseEntity getPrice( - @Parameter(description = "Date and time for price lookup (ISO format)", example = "2025-04-30T12:00:00") + @Parameter(description = "Date and time for price lookup (ISO format)", example = "2020-06-14T16:00:00") @RequestParam(name = "dateTime") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime dateTime, @Parameter(description = "Product ID", example = "35455") @RequestParam(name = "productId") Long productId, diff --git a/infrastructure/out/sql-repository/src/main/java/com/techivw/webprice/infrastructure/repositories/PriceEntityJPARepository.java b/infrastructure/out/sql-repository/src/main/java/com/techivw/webprice/infrastructure/repositories/PriceEntityJPARepository.java index b03c5da..a72854d 100644 --- a/infrastructure/out/sql-repository/src/main/java/com/techivw/webprice/infrastructure/repositories/PriceEntityJPARepository.java +++ b/infrastructure/out/sql-repository/src/main/java/com/techivw/webprice/infrastructure/repositories/PriceEntityJPARepository.java @@ -2,12 +2,19 @@ package com.techivw.webprice.infrastructure.repositories; import com.techivw.webprice.infrastructure.repositories.model.PriceEntity; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; +import java.time.LocalDateTime; import java.util.List; @Repository public interface PriceEntityJPARepository extends JpaRepository { - List findPricesByProductIdAndBrandId(Long productId, Long brandId); + @Query("SELECT p FROM PriceEntity p WHERE " + + "p.productId = :productId " + + "AND p.brandId = :brandId " + + "AND :dateTime BETWEEN p.startDate AND p.endDate") + List findPricesByProductIdAndBrandIdAndBetweenDateTime( + Long productId, Long brandId, LocalDateTime dateTime); } diff --git a/infrastructure/out/sql-repository/src/main/java/com/techivw/webprice/infrastructure/repositories/adapters/PriceRepositoryAdapter.java b/infrastructure/out/sql-repository/src/main/java/com/techivw/webprice/infrastructure/repositories/adapters/PriceRepositoryAdapter.java index 4d9984e..a48db16 100644 --- a/infrastructure/out/sql-repository/src/main/java/com/techivw/webprice/infrastructure/repositories/adapters/PriceRepositoryAdapter.java +++ b/infrastructure/out/sql-repository/src/main/java/com/techivw/webprice/infrastructure/repositories/adapters/PriceRepositoryAdapter.java @@ -8,6 +8,7 @@ import com.techivw.webprice.infrastructure.repositories.model.PriceEntity; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; +import java.time.LocalDateTime; import java.util.List; @Service @@ -17,9 +18,9 @@ public class PriceRepositoryAdapter implements PriceRepositoryPort { private final PriceEntityJPARepository repository; @Override - public List findPricesByProductIdAndBrandId(Long productId, Long brandId) { + public List findPricesByProductIdAndBrandIdAndDateTimeBetween(Long productId, Long brandId, LocalDateTime dateTime) { - List priceEntityList = repository.findPricesByProductIdAndBrandId(productId, brandId); + List priceEntityList = repository.findPricesByProductIdAndBrandIdAndBetweenDateTime(productId, brandId, dateTime); return PriceEntityMapper.toPriceList(priceEntityList); } diff --git a/infrastructure/out/sql-repository/src/test/java/com/techivw/webprice/infrastructure/repositories/adapters/PriceRepositoryAdapterTest.java b/infrastructure/out/sql-repository/src/test/java/com/techivw/webprice/infrastructure/repositories/adapters/PriceRepositoryAdapterTest.java index 21e4d5f..bd4dbcd 100644 --- a/infrastructure/out/sql-repository/src/test/java/com/techivw/webprice/infrastructure/repositories/adapters/PriceRepositoryAdapterTest.java +++ b/infrastructure/out/sql-repository/src/test/java/com/techivw/webprice/infrastructure/repositories/adapters/PriceRepositoryAdapterTest.java @@ -43,24 +43,24 @@ class PriceRepositoryAdapterTest { createPriceEntity(2) ); - when(repository.findPricesByProductIdAndBrandId( - eq(TEST_PRODUCT_ID), eq(TEST_BRAND_ID))) + when(repository.findPricesByProductIdAndBrandIdAndBetweenDateTime( + eq(TEST_PRODUCT_ID), eq(TEST_BRAND_ID), eq(TEST_DATE))) .thenReturn(priceEntities); - List result = adapter.findPricesByProductIdAndBrandId( - TEST_PRODUCT_ID, TEST_BRAND_ID); + List result = adapter.findPricesByProductIdAndBrandIdAndDateTimeBetween( + TEST_PRODUCT_ID, TEST_BRAND_ID, TEST_DATE); assertEquals(2, result.size()); } @Test void shouldReturnEmptyListWhenNoPriceEntitiesExist() { - when(repository.findPricesByProductIdAndBrandId( - eq(TEST_PRODUCT_ID), eq(TEST_BRAND_ID))) + when(repository.findPricesByProductIdAndBrandIdAndBetweenDateTime( + eq(TEST_PRODUCT_ID), eq(TEST_BRAND_ID), eq(TEST_DATE))) .thenReturn(Collections.emptyList()); - List result = adapter.findPricesByProductIdAndBrandId( - TEST_PRODUCT_ID, TEST_BRAND_ID); + List result = adapter.findPricesByProductIdAndBrandIdAndDateTimeBetween( + TEST_PRODUCT_ID, TEST_BRAND_ID, TEST_DATE); assertTrue(result.isEmpty()); }