Skip to content

Commit b8fa04b

Browse files
authored
Merge pull request #166 from YAPP-Github/refactor/PRODUCT-251
[Refactor] Cheer - CheerTag `@OneToMany` 로 개선
2 parents f87e69b + 9d95190 commit b8fa04b

File tree

6 files changed

+96
-28
lines changed

6 files changed

+96
-28
lines changed
Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package eatda.controller.cheer;
22

33
import eatda.domain.cheer.Cheer;
4-
import eatda.domain.cheer.CheerTag;
54
import eatda.domain.cheer.CheerTagName;
65
import eatda.domain.store.Store;
76
import java.util.List;
@@ -14,19 +13,13 @@ public record CheerResponse(
1413
List<CheerTagName> tags
1514
) {
1615

17-
public CheerResponse(Cheer cheer, List<CheerTag> cheerTags, Store store, String imageUrl) {
16+
public CheerResponse(Cheer cheer, Store store, String imageUrl) {
1817
this(
1918
store.getId(),
2019
cheer.getId(),
2120
imageUrl,
2221
cheer.getDescription(),
23-
toTagNames(cheerTags)
22+
cheer.getCheerTagNames()
2423
);
2524
}
26-
27-
private static List<CheerTagName> toTagNames(List<CheerTag> cheerTags) {
28-
return cheerTags.stream()
29-
.map(CheerTag::getName)
30-
.toList();
31-
}
3225
}

src/main/java/eatda/domain/cheer/Cheer.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
import jakarta.persistence.JoinColumn;
1717
import jakarta.persistence.ManyToOne;
1818
import jakarta.persistence.Table;
19+
import java.util.Collections;
20+
import java.util.List;
1921
import lombok.AccessLevel;
2022
import lombok.Getter;
2123
import lombok.NoArgsConstructor;
@@ -44,6 +46,9 @@ public class Cheer extends AuditingEntity {
4446
@Embedded
4547
private ImageKey imageKey;
4648

49+
@Embedded
50+
private CheerTags cheerTags;
51+
4752
@Column(name = "is_admin", nullable = false)
4853
private boolean isAdmin;
4954

@@ -53,6 +58,7 @@ public Cheer(Member member, Store store, String description, ImageKey imageKey)
5358
this.store = store;
5459
this.description = description;
5560
this.imageKey = imageKey;
61+
this.cheerTags = new CheerTags();
5662

5763
this.isAdmin = false;
5864
}
@@ -67,4 +73,15 @@ private void validateDescription(String description) {
6773
throw new BusinessException(BusinessErrorCode.INVALID_CHEER_DESCRIPTION);
6874
}
6975
}
76+
77+
public void setCheerTags(List<CheerTagName> cheerTagNames) {
78+
this.cheerTags.setTags(this, cheerTagNames);
79+
}
80+
81+
public List<CheerTagName> getCheerTagNames() {
82+
if (cheerTags == null) {
83+
return Collections.emptyList();
84+
}
85+
return cheerTags.getNames();
86+
}
7087
}

src/main/java/eatda/domain/cheer/CheerTagNames.java renamed to src/main/java/eatda/domain/cheer/CheerTags.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,29 @@
22

33
import eatda.exception.BusinessErrorCode;
44
import eatda.exception.BusinessException;
5+
import jakarta.persistence.CascadeType;
6+
import jakarta.persistence.Embeddable;
7+
import jakarta.persistence.OneToMany;
8+
import java.util.ArrayList;
59
import java.util.List;
610
import java.util.stream.Collectors;
711

8-
public class CheerTagNames {
12+
@Embeddable
13+
public class CheerTags {
914

1015
private static final int MAX_CHEER_TAGS_PER_TYPE = 2;
1116

12-
private final List<CheerTagName> cheerTagNames;
17+
@OneToMany(mappedBy = "cheer", cascade = CascadeType.ALL, orphanRemoval = true)
18+
private List<CheerTag> values = new ArrayList<>();
1319

14-
public CheerTagNames(List<CheerTagName> cheerTagNames) {
20+
public void setTags(Cheer cheer, List<CheerTagName> cheerTagNames) {
1521
validate(cheerTagNames);
16-
this.cheerTagNames = List.copyOf(cheerTagNames);
22+
List<CheerTag> cheerTags = cheerTagNames.stream()
23+
.map(name -> new CheerTag(cheer, name)) // cheer is set later
24+
.toList();
25+
26+
this.values.clear();
27+
this.values.addAll(cheerTags);
1728
}
1829

1930
private void validate(List<CheerTagName> cheerTagNames) {
@@ -41,9 +52,9 @@ private long maxCountByType(List<CheerTagName> cheerTagNames) {
4152
.orElse(0L);
4253
}
4354

44-
public List<CheerTag> toCheerTags(Cheer cheer) {
45-
return cheerTagNames.stream()
46-
.map(name -> new CheerTag(cheer, name))
55+
public List<CheerTagName> getNames() {
56+
return values.stream()
57+
.map(CheerTag::getName)
4758
.toList();
4859
}
4960
}

src/main/java/eatda/service/cheer/CheerService.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
import eatda.controller.cheer.CheersResponse;
99
import eatda.domain.ImageKey;
1010
import eatda.domain.cheer.Cheer;
11-
import eatda.domain.cheer.CheerTag;
12-
import eatda.domain.cheer.CheerTagNames;
1311
import eatda.domain.member.Member;
1412
import eatda.domain.store.Store;
1513
import eatda.domain.store.StoreSearchResult;
@@ -43,15 +41,15 @@ public CheerResponse registerCheer(CheerRegisterRequest request,
4341
StoreSearchResult result,
4442
ImageKey imageKey,
4543
long memberId) {
46-
CheerTagNames cheerTagNames = new CheerTagNames(request.tags());
4744
Member member = memberRepository.getById(memberId);
4845
validateRegisterCheer(member, request.storeKakaoId());
4946

5047
Store store = storeRepository.findByKakaoId(result.kakaoId())
5148
.orElseGet(() -> storeRepository.save(result.toStore())); // TODO 상점 조회/저장 동시성 이슈 해결
52-
Cheer cheer = cheerRepository.save(new Cheer(member, store, request.description(), imageKey));
53-
List<CheerTag> cheerTags = cheerTagRepository.saveAll(cheerTagNames.toCheerTags(cheer));
54-
return new CheerResponse(cheer, cheerTags, store, imageStorage.getPreSignedUrl(imageKey));
49+
Cheer cheer = new Cheer(member, store, request.description(), imageKey);
50+
cheer.setCheerTags(request.tags());
51+
Cheer savedCheer = cheerRepository.save(cheer);
52+
return new CheerResponse(savedCheer, store, imageStorage.getPreSignedUrl(imageKey));
5553
}
5654

5755
private void validateRegisterCheer(Member member, String storeKakaoId) {

src/test/java/eatda/domain/cheer/CheerTagNamesTest.java renamed to src/test/java/eatda/domain/cheer/CheerTagsTest.java

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,51 +4,79 @@
44
import static org.assertj.core.api.Assertions.assertThatCode;
55
import static org.junit.jupiter.api.Assertions.assertThrows;
66

7+
import eatda.domain.ImageKey;
8+
import eatda.domain.member.Member;
9+
import eatda.domain.store.District;
10+
import eatda.domain.store.Store;
11+
import eatda.domain.store.StoreCategory;
712
import eatda.exception.BusinessErrorCode;
813
import eatda.exception.BusinessException;
914
import java.util.Collections;
1015
import java.util.List;
1116
import org.junit.jupiter.api.Nested;
1217
import org.junit.jupiter.api.Test;
1318

14-
class CheerTagNamesTest {
19+
class CheerTagsTest {
20+
21+
private static final Member DEFAULT_MEMBER = new Member("socialId", "[email protected]", "nickname");
22+
private static final Store DEFAULT_STORE = Store.builder()
23+
.kakaoId("123456789")
24+
.category(StoreCategory.OTHER)
25+
.phoneNumber("010-1234-5678")
26+
.name("가게 이름")
27+
.placeUrl("https://place.kakao.com/123456789")
28+
.roadAddress("")
29+
.lotNumberAddress("서울특별시 강남구 역삼동 123-45")
30+
.district(District.GANGNAM)
31+
.latitude(37.5665)
32+
.longitude(126.978)
33+
.build();
34+
private static final Cheer DEFAULT_CHEER = new Cheer(DEFAULT_MEMBER, DEFAULT_STORE, "Great store!",
35+
new ImageKey("imageKey"));
1536

1637
@Nested
17-
class Validate {
38+
class SetTags {
1839

1940
@Test
2041
void 각_카테고리별_태그는_최대_개수가_정해져있다() {
2142
List<CheerTagName> tagNames = List.of(
2243
CheerTagName.OLD_STORE_MOOD, CheerTagName.ENERGETIC,
2344
CheerTagName.GROUP_RESERVATION, CheerTagName.LARGE_PARKING);
45+
CheerTags cheerTags = new CheerTags();
2446

25-
assertThatCode(() -> new CheerTagNames(tagNames)).doesNotThrowAnyException();
47+
assertThatCode(() -> cheerTags.setTags(DEFAULT_CHEER, tagNames)).doesNotThrowAnyException();
2648
}
2749

2850
@Test
2951
void 태그_이름은_비어있을_수_있다() {
3052
List<CheerTagName> tagNames = Collections.emptyList();
53+
CheerTags cheerTags = new CheerTags();
3154

32-
assertThatCode(() -> new CheerTagNames(tagNames)).doesNotThrowAnyException();
55+
assertThatCode(() -> cheerTags.setTags(DEFAULT_CHEER, tagNames)).doesNotThrowAnyException();
3356
}
3457

3558
@Test
3659
void 카테고리별_태그는_최대_개수를_초과할_수_없다() {
3760
List<CheerTagName> tagNames = List.of(
3861
CheerTagName.OLD_STORE_MOOD, CheerTagName.ENERGETIC, CheerTagName.GOOD_FOR_DATING);
62+
CheerTags cheerTags = new CheerTags();
3963

40-
BusinessException exception = assertThrows(BusinessException.class, () -> new CheerTagNames(tagNames));
64+
BusinessException exception = assertThrows(BusinessException.class,
65+
() -> cheerTags.setTags(DEFAULT_CHEER, tagNames));
4166

4267
assertThat(exception.getErrorCode()).isEqualTo(BusinessErrorCode.EXCEED_CHEER_TAGS_PER_TYPE);
4368
}
4469

4570
@Test
4671
void 태그_이름은_중복될_수_없다() {
4772
List<CheerTagName> tagNames = List.of(CheerTagName.OLD_STORE_MOOD, CheerTagName.OLD_STORE_MOOD);
73+
CheerTags cheerTags = new CheerTags();
4874

49-
BusinessException exception = assertThrows(BusinessException.class, () -> new CheerTagNames(tagNames));
75+
BusinessException exception = assertThrows(BusinessException.class,
76+
() -> cheerTags.setTags(DEFAULT_CHEER, tagNames));
5077

5178
assertThat(exception.getErrorCode()).isEqualTo(BusinessErrorCode.CHEER_TAGS_DUPLICATED);
5279
}
5380
}
81+
5482
}

src/test/java/eatda/service/cheer/CheerServiceTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,27 @@ class RegisterCheer {
145145
CheerTagName.GOOD_FOR_DATING, CheerTagName.CLEAN_RESTROOM)
146146
);
147147
}
148+
149+
@Test
150+
void 해당_응원의_응원_태그가_비어있어도_응원을_저장할_수_있다() {
151+
Member member = memberGenerator.generate("123");
152+
153+
CheerRegisterRequest request = new CheerRegisterRequest("123", "농민백암순대 본점", "맛있어요!", List.of());
154+
StoreSearchResult result = new StoreSearchResult(
155+
"123", StoreCategory.KOREAN, "02-755-5232", "농민백암순대 본점", "http://place.map.kakao.com/123",
156+
"서울시 강남구 역삼동 123-45", "서울시 강남구 역삼동 123-45", District.GANGNAM, 37.5665, 126.9780);
157+
ImageKey imageKey = new ImageKey("image-key");
158+
159+
CheerResponse response = cheerService.registerCheer(request, result, imageKey, member.getId());
160+
161+
Store foundStore = storeRepository.findByKakaoId("123").orElseThrow();
162+
assertAll(
163+
() -> assertThat(response.storeId()).isEqualTo(foundStore.getId()),
164+
() -> assertThat(response.cheerDescription()).isEqualTo("맛있어요!"),
165+
() -> assertThat(response.imageUrl()).isNotBlank(),
166+
() -> assertThat(response.tags()).isEmpty()
167+
);
168+
}
148169
}
149170

150171
@Nested

0 commit comments

Comments
 (0)