Skip to content

Commit a5e79e8

Browse files
committed
feat: Cheer 도메인 구현
1 parent 0c61e3d commit a5e79e8

File tree

6 files changed

+199
-22
lines changed

6 files changed

+199
-22
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package eatda.domain.store;
2+
3+
import eatda.domain.member.Member;
4+
import eatda.exception.BusinessErrorCode;
5+
import eatda.exception.BusinessException;
6+
import jakarta.persistence.Column;
7+
import jakarta.persistence.Entity;
8+
import jakarta.persistence.FetchType;
9+
import jakarta.persistence.GeneratedValue;
10+
import jakarta.persistence.GenerationType;
11+
import jakarta.persistence.Id;
12+
import jakarta.persistence.JoinColumn;
13+
import jakarta.persistence.ManyToOne;
14+
import jakarta.persistence.Table;
15+
import java.time.LocalDateTime;
16+
import lombok.AccessLevel;
17+
import lombok.Getter;
18+
import lombok.NoArgsConstructor;
19+
20+
@Table(name = "cheer")
21+
@Entity
22+
@Getter
23+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
24+
public class Cheer {
25+
26+
@Id
27+
@GeneratedValue(strategy = GenerationType.IDENTITY)
28+
private Long id;
29+
30+
@ManyToOne(fetch = FetchType.LAZY)
31+
@JoinColumn(name = "member_id", nullable = false)
32+
private Member member;
33+
34+
@ManyToOne(fetch = FetchType.LAZY)
35+
@JoinColumn(name = "store_id", nullable = false)
36+
private Store store;
37+
38+
@Column(nullable = false, columnDefinition = "TEXT")
39+
private String description;
40+
41+
@Column(name = "image_key", nullable = false, length = 511)
42+
private String imageKey;
43+
44+
@Column(name = "is_admin", nullable = false)
45+
private boolean isAdmin;
46+
47+
@Column(name = "created_at", nullable = false)
48+
private LocalDateTime createdAt;
49+
50+
public Cheer(Long id, Member member, Store store, String description, String imageKey) {
51+
validateDescription(description);
52+
validateImageKey(imageKey);
53+
this.id = id;
54+
this.member = member;
55+
this.store = store;
56+
this.description = description;
57+
this.imageKey = imageKey;
58+
59+
this.isAdmin = false;
60+
this.createdAt = LocalDateTime.now();
61+
}
62+
63+
private void validateDescription(String description) {
64+
if (description == null || description.isBlank()) {
65+
throw new BusinessException(BusinessErrorCode.INVALID_CHEER_DESCRIPTION);
66+
}
67+
}
68+
69+
private void validateImageKey(String imageKey) {
70+
if (imageKey != null && imageKey.isBlank()) {
71+
throw new BusinessException(BusinessErrorCode.INVALID_CHEER_IMAGE_KEY);
72+
}
73+
}
74+
}

src/main/java/eatda/exception/BusinessErrorCode.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ public enum BusinessErrorCode {
2222
OUT_OF_SEOUL_LATITUDE_RANGE("STO010", "서비스 지역(서울)을 벗어난 위도 값입니다."),
2323
OUT_OF_SEOUL_LONGITUDE_RANGE("STO011", "서비스 지역(서울)을 벗어난 경도 값입니다."),
2424

25+
// Cheer
26+
INVALID_CHEER_DESCRIPTION("CHE001", "응원 메시지는 필수입니다."),
27+
INVALID_CHEER_IMAGE_KEY("CHE002", "응원 이미지 키가 비어 있습니다.", HttpStatus.INTERNAL_SERVER_ERROR),
28+
2529
// Map
2630
MAP_SERVER_ERROR("MAP001", "지도 서버와의 통신 오류입니다.", HttpStatus.INTERNAL_SERVER_ERROR),
2731

src/main/resources/db/migration/V1__init.sql

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,37 @@ CREATE TABLE `member`
55
`social_id` VARCHAR(255) NOT NULL UNIQUE,
66
`nickname` VARCHAR(255) NULL,
77
`phone_number` VARCHAR(255) NULL,
8-
`opt_in_marketing` BOOLEAN NULL,
8+
`opt_in_marketing` BOOLEAN NULL,
99
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
1010
PRIMARY KEY (`id`)
1111
);
1212

13-
CREATE TABLE `store` (
14-
`id` BIGINT NOT NULL AUTO_INCREMENT,
15-
`kakao_id` VARCHAR(255) NOT NULL UNIQUE,
16-
`category` VARCHAR(50) NOT NULL,
17-
`phone_number` VARCHAR(255) NOT NULL,
18-
`name` VARCHAR(255) NOT NULL,
19-
`place_url` VARCHAR(255) NOT NULL,
20-
`road_address` VARCHAR(255) NOT NULL,
21-
`lot_number_address` VARCHAR(255) NOT NULL,
22-
`latitude` DOUBLE NOT NULL,
23-
`longitude` DOUBLE NOT NULL,
24-
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
25-
PRIMARY KEY (`id`)
13+
CREATE TABLE `store`
14+
(
15+
`id` BIGINT NOT NULL AUTO_INCREMENT,
16+
`kakao_id` VARCHAR(255) NOT NULL UNIQUE,
17+
`category` VARCHAR(50) NOT NULL,
18+
`phone_number` VARCHAR(255) NOT NULL,
19+
`name` VARCHAR(255) NOT NULL,
20+
`place_url` VARCHAR(255) NOT NULL,
21+
`road_address` VARCHAR(255) NOT NULL,
22+
`lot_number_address` VARCHAR(255) NOT NULL,
23+
`latitude` DOUBLE NOT NULL,
24+
`longitude` DOUBLE NOT NULL,
25+
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
26+
PRIMARY KEY (`id`)
2627
);
2728

29+
CREATE TABLE `cheer`
30+
(
31+
`id` BIGINT NOT NULL AUTO_INCREMENT,
32+
`member_id` BIGINT NOT NULL,
33+
`store_id` BIGINT NOT NULL,
34+
`description` TEXT NOT NULL,
35+
`image_key` VARCHAR(511) NOT NULL,
36+
`is_admin` BOOLEAN NOT NULL,
37+
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
38+
PRIMARY KEY (`id`),
39+
FOREIGN KEY (`member_id`) REFERENCES `member` (`id`) ON DELETE CASCADE,
40+
FOREIGN KEY (`store_id`) REFERENCES `store` (`id`) ON DELETE CASCADE
41+
);

src/main/resources/db/seed/dev/V2__dev_init_data.sql

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,28 @@ VALUES (1, 123456789, '[email protected]', '이승로', '01012345678', true),
77
(6, 324569987, '[email protected]', '박희수', '01043609998', false),
88
(7, 323487985, '[email protected]', '하아얀', '01065083298', false);
99

10-
INSERT INTO store (id, kakao_id, category, phone_number, name, place_url, road_address, lot_number_address, latitude, longitude)
11-
VALUES (1, '99999999999', 'KOREAN', '01012345678', '맛있는 한식집', 'https://place.map.kakao.com/17163273', '서울시 강남구 역삼동 123-45', '서울시 강남구 역삼동 123-45', 37.503708148482524, 127.05300772497776),
12-
(2, '99999999998', 'CHINESE', '01087654321', '아름다운 양식집', 'https://place.map.kakao.com/17163273', '서울시 강남구 역삼동 67-89', '서울시 강남구 역삼동 67-89', 37.4979, 127.0276),
13-
(3, '99999999997', 'JAPANESE', '01045678912', '정통 중식당', 'https://place.map.kakao.com/17163273', '서울시 강남구 역삼동 101-112', '서울시 강남구 역삼동 101-112', 37.56259825108099, 126.97715943361476),
14-
(4, '99999999996', 'WESTERN', '01078912345', '고급 양식 레스토랑', 'https://place.map.kakao.com/17163273', '', '서울시 강남구 역삼동 131-415', 37.4979, 127.0276),
15-
(5, '99999999995', 'ETC', '01034574568', '달콤한 디저트 카페', 'https://place.map.kakao.com/17163273', '서울시 강남구 역삼동 161-718', '서울시 강남구 역삼동 161-718', 37.49491300989233, 127.03150463098274),
16-
(6, '99999999994', 'ETC', '01043609998', '아늑한 커피숍', 'https://place.map.kakao.com/17163273', '서울시 강남구 역삼동 192-021', '서울시 강남구 역삼동 192-021', 37.5298343127044, 126.919484339847),
17-
(7, '99999999993', 'ETC', '01065083298', '빠른 패스트푸드점', 'https://place.map.kakao.com/17163273', '', '서울시 강남구 역삼동 222-324', 37.5036675804016, 127.05305858911);
10+
INSERT INTO store (id, kakao_id, category, phone_number, name, place_url, road_address, lot_number_address, latitude,
11+
longitude)
12+
VALUES (1, '99999999999', 'KOREAN', '01012345678', '맛있는 한식집', 'https://place.map.kakao.com/17163273',
13+
'서울시 강남구 역삼동 123-45', '서울시 강남구 역삼동 123-45', 37.503708148482524, 127.05300772497776),
14+
(2, '99999999998', 'CHINESE', '01087654321', '아름다운 양식집', 'https://place.map.kakao.com/17163273',
15+
'서울시 강남구 역삼동 67-89', '서울시 강남구 역삼동 67-89', 37.4979, 127.0276),
16+
(3, '99999999997', 'JAPANESE', '01045678912', '정통 중식당', 'https://place.map.kakao.com/17163273',
17+
'서울시 강남구 역삼동 101-112', '서울시 강남구 역삼동 101-112', 37.56259825108099, 126.97715943361476),
18+
(4, '99999999996', 'WESTERN', '01078912345', '고급 양식 레스토랑', 'https://place.map.kakao.com/17163273', '',
19+
'서울시 강남구 역삼동 131-415', 37.4979, 127.0276),
20+
(5, '99999999995', 'ETC', '01034574568', '달콤한 디저트 카페', 'https://place.map.kakao.com/17163273',
21+
'서울시 강남구 역삼동 161-718', '서울시 강남구 역삼동 161-718', 37.49491300989233, 127.03150463098274),
22+
(6, '99999999994', 'ETC', '01043609998', '아늑한 커피숍', 'https://place.map.kakao.com/17163273',
23+
'서울시 강남구 역삼동 192-021', '서울시 강남구 역삼동 192-021', 37.5298343127044, 126.919484339847),
24+
(7, '99999999993', 'ETC', '01065083298', '빠른 패스트푸드점', 'https://place.map.kakao.com/17163273', '',
25+
'서울시 강남구 역삼동 222-324', 37.5036675804016, 127.05305858911);
1826

27+
INSERT INTO cheer (id, member_id, store_id, description, image_key, is_admin)
28+
VALUES (1, 1, 1, '정말 맛있어요! 강추합니다!', 'default.jpg', true),
29+
(2, 2, 2, '서비스가 훌륭해요!', 'default.jpg', true),
30+
(3, 3, 3, '여기 음식이 정말 맛있어요!', 'default.jpg', true),
31+
(4, 4, 4, '분위기가 너무 좋아요!', 'default.jpg', true),
32+
(5, 5, 5, '디저트가 정말 맛있어요!', 'default.jpg', true),
33+
(6, 6, 6, '커피가 정말 맛있어요!', 'default.jpg', false),
34+
(7, 7, 7, '패스트푸드가 빠르고 맛있어요!', 'default.jpg', false);

src/main/resources/db/seed/local/V2__local_init_data.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,12 @@ VALUES (1, '99999999999', 'KOREAN', '01012345678', '맛있는 한식집', 'https
1515
(5, '99999999995', 'ETC', '01034574568', '달콤한 디저트 카페', 'https://place.map.kakao.com/17163273', '서울시 강남구 역삼동 161-718', '서울시 강남구 역삼동 161-718', 37.49491300989233, 127.03150463098274),
1616
(6, '99999999994', 'ETC', '01043609998', '아늑한 커피숍', 'https://place.map.kakao.com/17163273', '서울시 강남구 역삼동 192-021', '서울시 강남구 역삼동 192-021', 37.5298343127044, 126.919484339847),
1717
(7, '99999999993', 'ETC', '01065083298', '빠른 패스트푸드점', 'https://place.map.kakao.com/17163273', '', '서울시 강남구 역삼동 222-324', 37.5036675804016, 127.05305858911);
18+
19+
INSERT INTO cheer (id, member_id, store_id, description, image_key, is_admin)
20+
VALUES (1, 1, 1, '정말 맛있어요! 강추합니다!', 'default.jpg', true),
21+
(2, 2, 2, '서비스가 훌륭해요!', 'default.jpg', true),
22+
(3, 3, 3, '여기 음식이 정말 맛있어요!', 'default.jpg', true),
23+
(4, 4, 4, '분위기가 너무 좋아요!', 'default.jpg', true),
24+
(5, 5, 5, '디저트가 정말 맛있어요!', 'default.jpg', true),
25+
(6, 6, 6, '커피가 정말 맛있어요!', 'default.jpg', false),
26+
(7, 7, 7, '패스트푸드가 빠르고 맛있어요!', 'default.jpg', false);
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package eatda.domain.store;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
import static org.assertj.core.api.Assertions.assertThatCode;
5+
import static org.junit.jupiter.api.Assertions.assertThrows;
6+
7+
import eatda.domain.member.Member;
8+
import eatda.exception.BusinessErrorCode;
9+
import eatda.exception.BusinessException;
10+
import org.junit.jupiter.api.Nested;
11+
import org.junit.jupiter.api.Test;
12+
import org.junit.jupiter.params.ParameterizedTest;
13+
import org.junit.jupiter.params.provider.NullAndEmptySource;
14+
import org.junit.jupiter.params.provider.ValueSource;
15+
16+
class CheerTest {
17+
18+
private static final Member DEFAULT_MEMBER = new Member("socialId", "[email protected]", "nickname");
19+
private static final Store DEFAULT_STORE = Store.builder()
20+
.kakaoId("1234567890")
21+
.category(StoreCategory.CAFE)
22+
.phoneNumber("02-1234-5678")
23+
.name("Test Store")
24+
.placeUrl("https://place.kakao.com/1234567890")
25+
.roadAddress("서울시 성북구 대학로 1길 1")
26+
.lotNumberAddress("서울시 성북구 동선동 1-1")
27+
.latitude(37.5665)
28+
.longitude(126.978)
29+
.build();
30+
31+
@Nested
32+
class Validate {
33+
34+
@ParameterizedTest
35+
@NullAndEmptySource
36+
void 설명이_비어있으면_안된다(String description) {
37+
BusinessException exception = assertThrows(BusinessException.class, () -> {
38+
new Cheer(1L, DEFAULT_MEMBER, DEFAULT_STORE, description, "imageKey");
39+
});
40+
41+
assertThat(exception.getErrorCode()).isEqualTo(BusinessErrorCode.INVALID_CHEER_DESCRIPTION);
42+
}
43+
44+
@Test
45+
void 이미지_키는_null이_가능하다() {
46+
assertThatCode(() -> new Cheer(1L, DEFAULT_MEMBER, DEFAULT_STORE, "Great store!", null))
47+
.doesNotThrowAnyException();
48+
}
49+
50+
@ParameterizedTest
51+
@ValueSource(strings = {"", " ", "\t\n"})
52+
void 이미지_키는_비어있으면_안된다(String imageKey) {
53+
BusinessException exception = assertThrows(BusinessException.class, () -> {
54+
new Cheer(1L, DEFAULT_MEMBER, DEFAULT_STORE, "Great store!", "");
55+
});
56+
57+
assertThat(exception.getErrorCode()).isEqualTo(BusinessErrorCode.INVALID_CHEER_IMAGE_KEY);
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)