Skip to content

Commit 4c29abd

Browse files
committed
feat: '상점에 달린 태그 조회 API' 서비스 로직 구현
1 parent f71236a commit 4c29abd

File tree

6 files changed

+105
-0
lines changed

6 files changed

+105
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package eatda.controller.store;
2+
3+
import eatda.domain.cheer.CheerTag;
4+
import eatda.domain.cheer.CheerTagName;
5+
import java.util.List;
6+
7+
public record TagsResponse(List<CheerTagName> tags) {
8+
9+
public static TagsResponse from(List<CheerTag> cheerTags) {
10+
List<CheerTagName> cheerTagNames = cheerTags.stream()
11+
.map(CheerTag::getName)
12+
.distinct()
13+
.toList();
14+
return new TagsResponse(cheerTagNames);
15+
}
16+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package eatda.repository.cheer;
22

33
import eatda.domain.cheer.CheerTag;
4+
import eatda.domain.store.Store;
5+
import java.util.List;
46
import org.springframework.data.jpa.repository.JpaRepository;
57

68
public interface CheerTagRepository extends JpaRepository<CheerTag, Long> {
79

10+
List<CheerTag> findAllByCheerStore(Store storeId);
811
}

src/main/java/eatda/service/store/StoreService.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
import eatda.controller.store.StoreResponse;
1010
import eatda.controller.store.StoresInMemberResponse;
1111
import eatda.controller.store.StoresResponse;
12+
import eatda.controller.store.TagsResponse;
13+
import eatda.domain.cheer.CheerTag;
1214
import eatda.domain.store.Store;
1315
import eatda.domain.store.StoreCategory;
1416
import eatda.repository.cheer.CheerRepository;
17+
import eatda.repository.cheer.CheerTagRepository;
1518
import eatda.repository.store.StoreRepository;
1619
import eatda.storage.image.ImageStorage;
1720
import java.util.List;
@@ -28,6 +31,7 @@ public class StoreService {
2831

2932
private final StoreRepository storeRepository;
3033
private final CheerRepository cheerRepository;
34+
private final CheerTagRepository cheerTagRepository;
3135
private final ImageStorage imageStorage;
3236

3337
public StoreResponse getStore(long storeId) {
@@ -51,6 +55,13 @@ private List<Store> findStores(int page, int size, @Nullable String category) {
5155
StoreCategory.from(category), PageRequest.of(page, size));
5256
}
5357

58+
@Transactional(readOnly = true)
59+
public TagsResponse getStoreTags(long storeId) {
60+
Store store = storeRepository.getById(storeId);
61+
List<CheerTag> cheerTags = cheerTagRepository.findAllByCheerStore(store);
62+
return TagsResponse.from(cheerTags);
63+
}
64+
5465
public ImagesResponse getStoreImages(long storeId) {
5566
Store store = storeRepository.getById(storeId);
5667
List<String> imageUrls = cheerRepository.findAllImageKey(store)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package eatda.fixture;
2+
3+
import eatda.domain.cheer.Cheer;
4+
import eatda.domain.cheer.CheerTag;
5+
import eatda.domain.cheer.CheerTagName;
6+
import eatda.repository.cheer.CheerTagRepository;
7+
import java.util.List;
8+
import org.springframework.stereotype.Component;
9+
10+
@Component
11+
public class CheerTagGenerator {
12+
13+
private final CheerTagRepository cheerTagRepository;
14+
15+
public CheerTagGenerator(CheerTagRepository cheerTagRepository) {
16+
this.cheerTagRepository = cheerTagRepository;
17+
}
18+
19+
public List<CheerTag> generate(Cheer cheer, List<CheerTagName> tagNames) {
20+
return tagNames.stream()
21+
.map(name -> cheerTagRepository.save(new CheerTag(cheer, name)))
22+
.toList();
23+
}
24+
}

src/test/java/eatda/service/BaseServiceTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import eatda.client.oauth.OauthClient;
99
import eatda.domain.ImageKey;
1010
import eatda.fixture.CheerGenerator;
11+
import eatda.fixture.CheerTagGenerator;
1112
import eatda.fixture.MemberGenerator;
1213
import eatda.fixture.StoreGenerator;
1314
import eatda.fixture.StoryGenerator;
@@ -57,6 +58,9 @@ public abstract class BaseServiceTest {
5758
@Autowired
5859
protected CheerGenerator cheerGenerator;
5960

61+
@Autowired
62+
protected CheerTagGenerator cheerTagGenerator;
63+
6064
@Autowired
6165
protected StoryGenerator storyGenerator;
6266

src/test/java/eatda/service/store/StoreServiceTest.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
import eatda.controller.store.ImagesResponse;
88
import eatda.controller.store.StoreResponse;
99
import eatda.controller.store.StoresInMemberResponse;
10+
import eatda.controller.store.TagsResponse;
11+
import eatda.domain.cheer.Cheer;
12+
import eatda.domain.cheer.CheerTagName;
1013
import eatda.domain.member.Member;
1114
import eatda.domain.store.District;
1215
import eatda.domain.store.Store;
@@ -15,6 +18,7 @@
1518
import eatda.exception.BusinessException;
1619
import eatda.service.BaseServiceTest;
1720
import java.time.LocalDateTime;
21+
import java.util.List;
1822
import org.junit.jupiter.api.Nested;
1923
import org.junit.jupiter.api.Test;
2024
import org.springframework.beans.factory.annotation.Autowired;
@@ -154,6 +158,49 @@ class GetStores {
154158
}
155159
}
156160

161+
@Nested
162+
class GetStoreTags {
163+
164+
@Test
165+
void 음식점의_태그들을_조회한다() {
166+
Member member1 = memberGenerator.generate("111", "[email protected]", "nickname1");
167+
Member member2 = memberGenerator.generate("112", "[email protected]", "nickname2");
168+
Store store = storeGenerator.generate("농민백암순대", "서울 강남구 대치동 896-33");
169+
Cheer cheer1 = cheerGenerator.generateCommon(member1, store);
170+
Cheer cheer2 = cheerGenerator.generateCommon(member2, store);
171+
cheerTagGenerator.generate(cheer1, List.of(CheerTagName.INSTAGRAMMABLE, CheerTagName.ENERGETIC));
172+
cheerTagGenerator.generate(cheer2, List.of(CheerTagName.INSTAGRAMMABLE, CheerTagName.CLEAN_RESTROOM));
173+
174+
TagsResponse response = storeService.getStoreTags(store.getId());
175+
176+
assertThat(response.tags()).containsExactlyInAnyOrder(
177+
CheerTagName.INSTAGRAMMABLE, CheerTagName.ENERGETIC, CheerTagName.CLEAN_RESTROOM);
178+
}
179+
180+
@Test
181+
void 음식점의_태그가_없다면_빈_리스트를_반환한다() {
182+
Member member1 = memberGenerator.generate("111", "[email protected]", "nickname1");
183+
Member member2 = memberGenerator.generate("112", "[email protected]", "nickname2");
184+
Store store = storeGenerator.generate("농민백암순대", "서울 강남구 대치동 896-33");
185+
cheerGenerator.generateCommon(member1, store);
186+
cheerGenerator.generateCommon(member2, store);
187+
188+
TagsResponse response = storeService.getStoreTags(store.getId());
189+
190+
assertThat(response.tags()).isEmpty();
191+
}
192+
193+
@Test
194+
void 음식점이_존재하지_않으면_예외를_발생시킨다() {
195+
long nonExistentStoreId = 999L;
196+
197+
BusinessException exception = assertThrows(BusinessException.class,
198+
() -> storeService.getStoreTags(nonExistentStoreId));
199+
200+
assertThat(exception.getErrorCode()).isEqualTo(BusinessErrorCode.STORE_NOT_FOUND);
201+
}
202+
}
203+
157204
@Nested
158205
class GetStoreImages {
159206

0 commit comments

Comments
 (0)