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,6 +1,7 @@
package in.koreatech.koin.domain.shop.controller;

import static in.koreatech.koin.domain.user.model.UserType.*;
import static in.koreatech.koin.global.code.ApiResponseCode.*;
import static io.swagger.v3.oas.annotations.enums.ParameterIn.PATH;

import java.util.List;
Expand All @@ -16,6 +17,7 @@
import in.koreatech.koin.domain.shop.dto.shop.ShopsFilterCriteriaV3;
import in.koreatech.koin.domain.shop.dto.shop.ShopsSortCriteria;
import in.koreatech.koin.domain.shop.dto.shop.ShopsSortCriteriaV3;
import in.koreatech.koin.domain.shop.dto.shop.response.OpenShopsCountResponse;
import in.koreatech.koin.domain.shop.dto.shop.response.ShopCategoriesResponse;
import in.koreatech.koin.domain.shop.dto.shop.response.ShopResponse;
import in.koreatech.koin.domain.shop.dto.shop.response.ShopResponseV2;
Expand All @@ -24,7 +26,6 @@
import in.koreatech.koin.domain.shop.dto.shop.response.ShopsResponseV2;
import in.koreatech.koin.domain.shop.dto.shop.response.ShopsResponseV3;
import in.koreatech.koin.global.auth.Auth;
import in.koreatech.koin.global.code.ApiResponseCode;
import in.koreatech.koin.global.code.ApiResponseCodes;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
Expand Down Expand Up @@ -56,7 +57,7 @@ ResponseEntity<ShopResponse> getShopById(
- openTime, closeTime 응답값 추가
""")
@ApiResponseCodes({
ApiResponseCode.OK
OK
})
@GetMapping("/v2/shops/{id}")
ResponseEntity<ShopResponseV2> getShopByIdV2(
Expand Down Expand Up @@ -87,6 +88,13 @@ ResponseEntity<ShopSummaryResponse> getShopSummary(
@GetMapping("/shops")
ResponseEntity<ShopsResponse> getShops();

@ApiResponseCodes({
OK
})
@Operation(summary = "현재 영업 중인 상점 개수 조회")
Comment thread
dh2906 marked this conversation as resolved.
@GetMapping("/shops/open/count")
ResponseEntity<OpenShopsCountResponse> getOpenShopsCount();

@ApiResponses(
value = {
@ApiResponse(responseCode = "200"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import in.koreatech.koin.domain.shop.dto.shop.ShopsFilterCriteriaV3;
import in.koreatech.koin.domain.shop.dto.shop.ShopsSortCriteria;
import in.koreatech.koin.domain.shop.dto.shop.ShopsSortCriteriaV3;
import in.koreatech.koin.domain.shop.dto.shop.response.OpenShopsCountResponse;
import in.koreatech.koin.domain.shop.dto.shop.response.ShopCategoriesResponse;
import in.koreatech.koin.domain.shop.dto.shop.response.ShopResponse;
import in.koreatech.koin.domain.shop.dto.shop.response.ShopResponseV2;
Expand Down Expand Up @@ -68,6 +69,12 @@ public ResponseEntity<ShopsResponse> getShops() {
return ResponseEntity.ok(shopsResponse);
}

@GetMapping("/shops/open/count")
public ResponseEntity<OpenShopsCountResponse> getOpenShopsCount() {
OpenShopsCountResponse response = shopService.getOpenShopsCount();
return ResponseEntity.ok(response);
}

@GetMapping("/shops/categories")
public ResponseEntity<ShopCategoriesResponse> getShopsCategories() {
ShopCategoriesResponse shopCategoriesResponse = shopService.getShopsCategories();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package in.koreatech.koin.domain.shop.dto.shop.response;

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

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

public record OpenShopsCountResponse(
@Schema(example = "24", description = "현재 영업 중인 상점 개수", requiredMode = REQUIRED)
Integer count
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import in.koreatech.koin.domain.shop.exception.ShopNotFoundException;
import in.koreatech.koin.domain.shop.model.shop.Shop;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand Down Expand Up @@ -36,6 +37,41 @@ default Shop getById(Integer shopId) {
""")
List<Shop> findAll();

@Query("""
SELECT COUNT(DISTINCT s.id)
FROM Shop s
JOIN s.shopOpens so
WHERE s.isDeleted = false
AND so.isDeleted = false
AND so.closed = false
AND (
(
so.dayOfWeek = :currentDayOfWeek
AND (
(
so.closeTime > so.openTime
AND so.openTime <= :currentTime
AND so.closeTime >= :currentTime
)
OR (
so.closeTime <= so.openTime
AND so.openTime <= :currentTime
)
)
)
OR (
so.dayOfWeek = :previousDayOfWeek
AND so.closeTime <= so.openTime
AND so.closeTime >= :currentTime
)
)
""")
Long countOpenShops(
@Param("currentDayOfWeek") String currentDayOfWeek,
@Param("previousDayOfWeek") String previousDayOfWeek,
@Param("currentTime") LocalTime currentTime
);

@Query("""
SELECT s
FROM Shop s
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.TextStyle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.springframework.data.domain.Sort;
Expand All @@ -24,6 +26,7 @@
import in.koreatech.koin.domain.shop.dto.shop.ShopsFilterCriteriaV3;
import in.koreatech.koin.domain.shop.dto.shop.ShopsSortCriteria;
import in.koreatech.koin.domain.shop.dto.shop.ShopsSortCriteriaV3;
import in.koreatech.koin.domain.shop.dto.shop.response.OpenShopsCountResponse;
import in.koreatech.koin.domain.shop.dto.shop.response.ShopCategoriesResponse;
import in.koreatech.koin.domain.shop.dto.shop.response.ShopResponse;
import in.koreatech.koin.domain.shop.dto.shop.response.ShopResponseV2;
Expand Down Expand Up @@ -82,6 +85,14 @@ public ShopsResponse getShops() {
return ShopsResponse.from(shops, eventDuration, now);
}

public OpenShopsCountResponse getOpenShopsCount() {
LocalDateTime now = LocalDateTime.now(clock);
String currentDayOfWeek = getDayOfWeek(now);
String previousDayOfWeek = getDayOfWeek(now.minusDays(1));
Long count = shopRepository.countOpenShops(currentDayOfWeek, previousDayOfWeek, now.toLocalTime());
return new OpenShopsCountResponse(Math.toIntExact(count));
}

public ShopCategoriesResponse getShopsCategories() {
List<ShopCategory> shopCategories = shopCategoryRepository.findAll(Sort.by("orderIndex"));
return ShopCategoriesResponse.from(shopCategories);
Expand Down Expand Up @@ -178,4 +189,8 @@ public void publishCallNotification(Integer shopId, Integer studentId) {
private boolean isSubscribeReviewNotification(Integer studentId) {
return notificationSubscribeRepository.existsByUserIdAndSubscribeTypeAndDetailTypeIsNull(studentId, REVIEW_PROMPT);
}

private String getDayOfWeek(LocalDateTime dateTime) {
return dateTime.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.US).toUpperCase();
}
}
16 changes: 16 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 @@ -429,6 +429,22 @@ void setUp() {
""", 마슬랜_영업여부, 신전_떡볶이_영업여부)));
}

@Test
void 현재_영업중인_상점_개수를_조회한다() throws Exception {
shopFixture.영업중이_아닌_신전_떡볶이(owner);

// 2024-01-15 12:00 월요일 기준
mockMvc.perform(
get("/shops/open/count")
)
.andExpect(status().isOk())
.andExpect(content().json("""
{
"count": 1
}
"""));
}

@Test
void 상점의_정렬된_모든_카테고리_조회() throws Exception {
shopCategoryFixture.카테고리_일반음식(shopParentCategory_가게); // 카테고리_치킨이 먼저 생성됨
Expand Down
Loading