Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package in.koreatech.koin.domain.shop.controller;

import static in.koreatech.koin.global.code.ApiResponseCode.OK;

import in.koreatech.koin.domain.shop.dto.event.response.ShopEventCountResponse;
import in.koreatech.koin.domain.shop.dto.event.response.ShopEventsWithBannerUrlResponse;
import in.koreatech.koin.domain.shop.dto.event.response.ShopEventsWithThumbnailUrlResponse;
import in.koreatech.koin.global.code.ApiResponseCodes;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
Expand Down Expand Up @@ -40,4 +44,11 @@ ResponseEntity<ShopEventsWithThumbnailUrlResponse> getShopEvents(
@Operation(summary = "모든 상점의 모든 이벤트 조회")
@GetMapping("/shops/events")
ResponseEntity<ShopEventsWithBannerUrlResponse> getShopAllEvent();

@ApiResponseCodes({
OK
})
@Operation(summary = "이벤트 진행 중인 상점 개수 조회")
@GetMapping("/shops/events/count")
ResponseEntity<ShopEventCountResponse> getEventShopCount();
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package in.koreatech.koin.domain.shop.controller;

import in.koreatech.koin.domain.shop.dto.event.response.ShopEventCountResponse;
import in.koreatech.koin.domain.shop.dto.event.response.ShopEventsWithBannerUrlResponse;
import in.koreatech.koin.domain.shop.dto.event.response.ShopEventsWithThumbnailUrlResponse;
import in.koreatech.koin.domain.shop.service.ShopEventService;
import in.koreatech.koin.domain.shop.service.ShopService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
Expand All @@ -29,4 +29,10 @@ public ResponseEntity<ShopEventsWithBannerUrlResponse> getShopAllEvent() {
var response = shopEventService.getAllEvents();
return ResponseEntity.ok(response);
}

@GetMapping("/shops/events/count")
public ResponseEntity<ShopEventCountResponse> getEventShopCount() {
var response = shopEventService.getEventShopCount();
return ResponseEntity.ok(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package in.koreatech.koin.domain.shop.dto.event.response;

import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;

import io.swagger.v3.oas.annotations.media.Schema;

public record ShopEventCountResponse(
@Schema(example = "5", description = "이벤트 진행 중인 상점 개수", requiredMode = REQUIRED)
Integer count
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,17 @@ Long countOpenShops(
""")
List<Shop> findAllWithEventArticles();

@Query("""
SELECT COUNT(DISTINCT s.id)
FROM Shop s
JOIN s.eventArticles e
WHERE s.isDeleted = false
AND e.isDeleted = false
AND e.startDate <= :now
AND e.endDate >= :now
""")
Long countShopsWithOngoingEvent(@Param("now") LocalDate now);

@Query("""
SELECT new in.koreatech.koin.domain.shop.dto.shop.ShopNotificationQueryResponse(
s.id,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package in.koreatech.koin.domain.shop.service;

import in.koreatech.koin.domain.shop.dto.event.response.ShopEventCountResponse;
import in.koreatech.koin.domain.shop.dto.event.response.ShopEventsWithBannerUrlResponse;
import in.koreatech.koin.domain.shop.dto.event.response.ShopEventsWithThumbnailUrlResponse;
import in.koreatech.koin.domain.shop.model.shop.Shop;
import in.koreatech.koin.domain.shop.repository.shop.ShopRepository;
import java.time.Clock;
import java.time.LocalDate;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -27,4 +29,10 @@ public ShopEventsWithBannerUrlResponse getAllEvents() {
List<Shop> shops = shopRepository.findAllWithEventArticles();
return ShopEventsWithBannerUrlResponse.of(shops, clock);
}

public ShopEventCountResponse getEventShopCount() {
LocalDate now = LocalDate.now(clock);
Long count = shopRepository.countShopsWithOngoingEvent(now);
return new ShopEventCountResponse(Math.toIntExact(count));
}
}
20 changes: 20 additions & 0 deletions src/test/java/in/koreatech/koin/acceptance/domain/ShopApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,26 @@ void setUp() {
"""));
}

@Test
void 이벤트_진행중인_상점_개수를_조회한다() throws Exception {
Shop 영업중인_티바 = shopFixture.영업중인_티바(owner);
Shop 영업중이_아닌_신전떡볶이 = shopFixture.영업중이_아닌_신전_떡볶이(owner);
eventArticleFixture.할인_이벤트(마슬랜, LocalDate.now(clock).minusDays(3), LocalDate.now(clock).plusDays(3));
eventArticleFixture.참여_이벤트(마슬랜, LocalDate.now(clock).minusDays(3), LocalDate.now(clock).plusDays(3));
eventArticleFixture.참여_이벤트(영업중인_티바, LocalDate.now(clock), LocalDate.now(clock).plusDays(10));
eventArticleFixture.할인_이벤트(영업중이_아닌_신전떡볶이, LocalDate.now(clock).minusDays(10), LocalDate.now(clock).minusDays(1));

mockMvc.perform(
get("/shops/events/count")
)
.andExpect(status().isOk())
.andExpect(content().json("""
{
"count": 2
}
"""));
}

@Test
void 리뷰_평점순으로_정렬하여_모든_상점을_조회한다() throws Exception {
Shop 영업중인_티바 = shopFixture.영업중인_티바(owner);
Expand Down
Loading