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
7 changes: 7 additions & 0 deletions src/main/java/eatda/controller/store/StoreController.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

Expand All @@ -21,6 +22,12 @@ public ResponseEntity<StoresResponse> getStores(@RequestParam @Min(1) @Max(50) i
return ResponseEntity.ok(storeService.getStores(size));
}

@GetMapping("/api/shops/{storeId}")
public ResponseEntity<StoreResponse> getStore(@PathVariable long storeId) {
StoreResponse response = storeService.getStore(storeId);
return ResponseEntity.ok(response);
}

@GetMapping("/api/shop/search")
public ResponseEntity<StoreSearchResponses> searchStore(@RequestParam String query, LoginMember member) {
StoreSearchResponses response = storeService.searchStores(query);
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/eatda/controller/store/StoreResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package eatda.controller.store;

import eatda.domain.store.Store;

public record StoreResponse(
long id,
String kakaoId,
String name,
String district,
String neighborhood,
String category,
String placeUrl
) {

public StoreResponse(Store store) {
this(
store.getId(),
store.getKakaoId(),
store.getName(),
store.getAddressDistrict(),
store.getAddressNeighborhood(),
store.getCategory().getCategoryName(),
store.getPlaceUrl()
);
}
}
12 changes: 9 additions & 3 deletions src/main/java/eatda/repository/store/StoreRepository.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
package eatda.repository.store;

import eatda.domain.store.Store;
import eatda.exception.BusinessErrorCode;
import eatda.exception.BusinessException;
import java.util.List;
import java.util.Optional;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
import org.springframework.data.jpa.repository.JpaRepository;

public interface StoreRepository extends Repository<Store, Long> {
public interface StoreRepository extends JpaRepository<Store, Long> {

Store save(Store store);
@Override
default Store getById(Long id) {
return findById(id)
.orElseThrow(() -> new BusinessException(BusinessErrorCode.STORE_NOT_FOUND));
}

Optional<Store> findByKakaoId(String kakaoId);

Expand Down
6 changes: 6 additions & 0 deletions src/main/java/eatda/service/store/StoreService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import eatda.client.map.MapClient;
import eatda.client.map.StoreSearchResult;
import eatda.controller.store.StorePreviewResponse;
import eatda.controller.store.StoreResponse;
import eatda.controller.store.StoreSearchResponses;
import eatda.controller.store.StoresResponse;
import eatda.domain.store.Store;
Expand All @@ -28,6 +29,11 @@ public class StoreService {
private final CheerRepository cheerRepository;
private final ImageStorage imageStorage;

public StoreResponse getStore(long storeId) {
Store store = storeRepository.getById(storeId);
return new StoreResponse(store);
}

// TODO : N+1 문제 해결
public StoresResponse getStores(int size) {
return storeRepository.findAllByOrderByCreatedAtDesc(Pageable.ofSize(size))
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/application-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jwt:
cors:
origin:
- "http://localhost:3000"
- "https://api-dev.eatda.net"
- "https://dev.eatda.net"

oauth:
client-id: ${OAUTH_CLIENT_ID}
Expand Down
26 changes: 26 additions & 0 deletions src/test/java/eatda/controller/store/StoreControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,32 @@

class StoreControllerTest extends BaseControllerTest {

@Nested
class GetStore {

@Test
void 음식점_정보를_조회한다() {
Member member = memberGenerator.generate("111");
Store store = storeGenerator.generate("농민백암순대", "서울 강남구 대치동 896-33");
cheerGenerator.generateCommon(member, store, "image-key");

StoreResponse response = given()
.pathParam("storeId", store.getId())
.when()
.get("/api/shops/{storeId}")
.then()
.statusCode(200)
.extract().as(StoreResponse.class);

assertAll(
() -> assertThat(response.id()).isEqualTo(store.getId()),
() -> assertThat(response.name()).isEqualTo(store.getName()),
() -> assertThat(response.district()).isEqualTo("강남구"),
() -> assertThat(response.neighborhood()).isEqualTo("대치동")
);
}
}

@Nested
class GetStores {

Expand Down
64 changes: 62 additions & 2 deletions src/test/java/eatda/document/store/StoreDocumentTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
Expand All @@ -13,6 +14,7 @@
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;

import eatda.controller.store.StorePreviewResponse;
import eatda.controller.store.StoreResponse;
import eatda.controller.store.StoreSearchResponse;
import eatda.controller.store.StoreSearchResponses;
import eatda.controller.store.StoresResponse;
Expand All @@ -32,6 +34,64 @@

public class StoreDocumentTest extends BaseDocumentTest {

@Nested
class GetStore {
RestDocsRequest requestDocument = request()
.tag(Tag.STORE_API)
.summary("음식점 정보 조회")
.pathParameter(
parameterWithName("storeId").description("음식점 ID")
);

RestDocsResponse responseDocument = response()
.responseBodyField(
fieldWithPath("id").type(NUMBER).description("음식점 ID"),
fieldWithPath("kakaoId").type(STRING).description("카카오 음식점 ID"),
fieldWithPath("name").type(STRING).description("음식점 이름"),
fieldWithPath("district").type(STRING).description("음식점 주소 (구)"),
fieldWithPath("neighborhood").type(STRING).description("음식점 주소 (동)"),
fieldWithPath("category").type(STRING).description("음식점 카테고리"),
fieldWithPath("placeUrl").type(STRING).description("음식점 카카오맵 URL")
);

@Test
void 음식점_정보를_조회() {
StoreResponse response = new StoreResponse(1L, "17163273", "농민백암순대", "강남구", "대치동",
"한식", "https://place.map.kakao.com/17163273");
doReturn(response).when(storeService).getStore(anyLong());

long storeId = 1L;
var document = document("store/get-store", 200)
.request(requestDocument)
.response(responseDocument)
.build();

given(document)
.contentType(ContentType.JSON)
.pathParam("storeId", storeId)
.when().get("/api/shops/{storeId}")
.then().statusCode(200);
}

@EnumSource(value = BusinessErrorCode.class, names = {"STORE_NOT_FOUND"})
@ParameterizedTest
void 음식점_정보_조회_실패(BusinessErrorCode errorCode) {
doThrow(new BusinessException(errorCode)).when(storeService).getStore(anyLong());

long storeId = 1L;
var document = document("store/get-store", errorCode)
.request(requestDocument)
.response(ERROR_RESPONSE)
.build();

given(document)
.contentType(ContentType.JSON)
.pathParam("storeId", storeId)
.when().get("/api/shops/{storeId}")
.then().statusCode(errorCode.getStatus().value());
}
}

@Nested
class GetStores {

Expand Down Expand Up @@ -62,7 +122,7 @@ class GetStores {
doReturn(response).when(storeService).getStores(anyInt());

int size = 2;
var document = document("store/get", 200)
var document = document("store/get-stores", 200)
.request(requestDocument)
.response(responseDocument)
.build();
Expand All @@ -80,7 +140,7 @@ class GetStores {
doThrow(new BusinessException(errorCode)).when(storeService).getStores(anyInt());

int size = 2;
var document = document("store/get", errorCode)
var document = document("store/get-stores", errorCode)
.request(requestDocument)
.response(ERROR_RESPONSE)
.build();
Expand Down
34 changes: 34 additions & 0 deletions src/test/java/eatda/service/store/StoreServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;

import eatda.client.map.StoreSearchResult;
import eatda.controller.store.StoreResponse;
import eatda.domain.member.Member;
import eatda.domain.store.Store;
import eatda.exception.BusinessErrorCode;
import eatda.exception.BusinessException;
import eatda.service.BaseServiceTest;
import java.util.List;
import org.junit.jupiter.api.Nested;
Expand All @@ -19,6 +23,36 @@ class StoreServiceTest extends BaseServiceTest {
@Autowired
private StoreService storeService;

@Nested
class GetStore {

@Test
void 음식점_정보를_조회한다() {
Member member = memberGenerator.generate("111");
Store store = storeGenerator.generate("농민백암순대", "서울 강남구 대치동 896-33");
cheerGenerator.generateCommon(member, store, "image-key");

StoreResponse response = storeService.getStore(store.getId());

assertAll(
() -> assertThat(response.id()).isEqualTo(store.getId()),
() -> assertThat(response.name()).isEqualTo(store.getName()),
() -> assertThat(response.district()).isEqualTo("강남구"),
() -> assertThat(response.neighborhood()).isEqualTo("대치동")
);
}

@Test
void 해당_음식점이_없을_경우_예외를_던진다() {
long nonExistentStoreId = 999L;

BusinessException exception = assertThrows(BusinessException.class,
() -> storeService.getStore(nonExistentStoreId));

assertThat(exception.getErrorCode()).isEqualTo(BusinessErrorCode.STORE_NOT_FOUND);
}
}

@Nested
class GetStores {

Expand Down