Skip to content

Commit 7800c55

Browse files
authored
[Feat] 나만의 맛집 코멘트 등록 API 구현
2 parents aff39a4 + 571a7dd commit 7800c55

28 files changed

+595
-164
lines changed

src/main/java/eatda/client/map/StoreSearchResult.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
44
import com.fasterxml.jackson.annotation.JsonProperty;
5+
import eatda.domain.store.Store;
6+
import eatda.domain.store.StoreCategory;
7+
import java.util.Map;
58

69
@JsonIgnoreProperties(ignoreUnknown = true)
710
public record StoreSearchResult(
@@ -17,6 +20,17 @@ public record StoreSearchResult(
1720
@JsonProperty("x") double longitude
1821
) {
1922

23+
private static final Map<String, StoreCategory> PREFIX_TO_CATEGORY = Map.of(
24+
"음식점 > 한식", StoreCategory.KOREAN,
25+
"음식점 > 중식", StoreCategory.CHINESE,
26+
"음식점 > 일식", StoreCategory.JAPANESE,
27+
"음식점 > 양식", StoreCategory.WESTERN,
28+
"음식점 > 카페", StoreCategory.CAFE,
29+
"음식점 > 간식 > 제과,베이커리", StoreCategory.BAKERY,
30+
"음식점 > 술집", StoreCategory.PUB,
31+
"음식점 > 패스트푸드", StoreCategory.FAST_FOOD
32+
);
33+
2034
public boolean isFoodStore() {
2135
return "FD6".equals(categoryGroupCode);
2236
}
@@ -27,4 +41,31 @@ public boolean isInSeoul() {
2741
}
2842
return lotNumberAddress.trim().startsWith("서울");
2943
}
44+
45+
public StoreCategory getStoreCategory() {
46+
if (categoryName == null) {
47+
return StoreCategory.OTHER;
48+
}
49+
50+
return PREFIX_TO_CATEGORY.entrySet()
51+
.stream()
52+
.filter(entry -> categoryName.startsWith(entry.getKey()))
53+
.map(Map.Entry::getValue)
54+
.findFirst()
55+
.orElse(StoreCategory.OTHER);
56+
}
57+
58+
public Store toStore() {
59+
return Store.builder()
60+
.kakaoId(kakaoId)
61+
.category(getStoreCategory())
62+
.phoneNumber(phoneNumber)
63+
.name(name)
64+
.placeUrl(placeUrl)
65+
.roadAddress(roadAddress)
66+
.lotNumberAddress(lotNumberAddress)
67+
.latitude(latitude)
68+
.longitude(longitude)
69+
.build();
70+
}
3071
}

src/main/java/eatda/controller/store/CheerController.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,34 @@
11
package eatda.controller.store;
22

3+
import eatda.controller.web.auth.LoginMember;
34
import eatda.service.store.CheerService;
45
import jakarta.validation.constraints.Max;
56
import jakarta.validation.constraints.Min;
67
import lombok.RequiredArgsConstructor;
8+
import org.springframework.http.HttpStatus;
79
import org.springframework.http.ResponseEntity;
810
import org.springframework.web.bind.annotation.GetMapping;
11+
import org.springframework.web.bind.annotation.PostMapping;
912
import org.springframework.web.bind.annotation.RequestParam;
13+
import org.springframework.web.bind.annotation.RequestPart;
1014
import org.springframework.web.bind.annotation.RestController;
15+
import org.springframework.web.multipart.MultipartFile;
1116

1217
@RestController
1318
@RequiredArgsConstructor
1419
public class CheerController {
1520

1621
private final CheerService cheerService;
1722

23+
@PostMapping("/api/cheer")
24+
public ResponseEntity<CheerResponse> registerCheer(@RequestPart("request") CheerRegisterRequest request,
25+
@RequestPart(value = "image", required = false) MultipartFile image,
26+
LoginMember member) {
27+
CheerResponse response = cheerService.registerCheer(request, image, member.id());
28+
return ResponseEntity.status(HttpStatus.CREATED)
29+
.body(response);
30+
}
31+
1832
@GetMapping("/api/cheer")
1933
public ResponseEntity<CheersResponse> getCheers(@RequestParam @Min(1) @Max(50) int size) {
2034
CheersResponse response = cheerService.getCheers(size);
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package eatda.controller.store;
2+
3+
public record CheerRegisterRequest(
4+
String storeKakaoId,
5+
String storeName,
6+
String description
7+
) {
8+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package eatda.controller.store;
2+
3+
import eatda.domain.store.Cheer;
4+
import eatda.domain.store.Store;
5+
6+
public record CheerResponse(
7+
long storeId,
8+
long cheerId,
9+
String imageUrl,
10+
String cheerDescription
11+
) {
12+
13+
public CheerResponse(Cheer cheer, String imageUrl, Store store) {
14+
this(
15+
store.getId(),
16+
cheer.getId(),
17+
imageUrl,
18+
cheer.getDescription()
19+
);
20+
}
21+
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package eatda.controller.story;
22

3+
import eatda.domain.store.StoreCategory;
4+
35
public record FilteredSearchResult(
46
String kakaoId,
57
String name,
68
String roadAddress,
79
String lotNumberAddress,
8-
String category
10+
StoreCategory category
911
) {
1012
}

src/main/java/eatda/domain/store/Store.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import jakarta.persistence.GenerationType;
1111
import jakarta.persistence.Id;
1212
import jakarta.persistence.Table;
13-
import java.time.LocalDateTime;
1413
import lombok.AccessLevel;
1514
import lombok.Builder;
1615
import lombok.Getter;

src/main/java/eatda/domain/store/StoreCategory.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@ public enum StoreCategory {
1313
JAPANESE("일식"),
1414
WESTERN("양식"),
1515
CAFE("카페"),
16-
DESSERT("디저트"),
16+
BAKERY("베이커리"),
1717
PUB("술집"),
1818
FAST_FOOD("패스트푸드"),
19-
CONVENIENCE("편의점"),
2019
OTHER("기타");
2120

2221
private final String categoryName;

src/main/java/eatda/domain/story/Story.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
import eatda.domain.AuditingEntity;
44
import eatda.domain.member.Member;
5+
import eatda.domain.store.StoreCategory;
56
import eatda.exception.BusinessErrorCode;
67
import eatda.exception.BusinessException;
78
import jakarta.persistence.Column;
89
import jakarta.persistence.Entity;
10+
import jakarta.persistence.EnumType;
11+
import jakarta.persistence.Enumerated;
912
import jakarta.persistence.FetchType;
1013
import jakarta.persistence.GeneratedValue;
1114
import jakarta.persistence.GenerationType;
@@ -44,8 +47,9 @@ public class Story extends AuditingEntity {
4447
@Column(name = "store_lot_number_address", nullable = false)
4548
private String storeLotNumberAddress;
4649

50+
@Enumerated(EnumType.STRING)
4751
@Column(name = "store_category", nullable = false)
48-
private String storeCategory;
52+
private StoreCategory storeCategory;
4953

5054
@Column(name = "description", nullable = false)
5155
private String description;
@@ -57,7 +61,7 @@ public class Story extends AuditingEntity {
5761
private Story(
5862
Member member,
5963
String storeKakaoId,
60-
String storeCategory,
64+
StoreCategory storeCategory,
6165
String storeName,
6266
String storeRoadAddress,
6367
String storeLotNumberAddress,
@@ -86,7 +90,7 @@ private void validateMember(Member member) {
8690

8791
private void validateStore(
8892
String storeKakaoId,
89-
String storeCategory,
93+
StoreCategory storeCategory,
9094
String storeName,
9195
String roadAddress,
9296
String lotNumberAddress
@@ -127,8 +131,8 @@ private void validateStoreLotNumberAddress(String lotNumberAddress) {
127131
}
128132
}
129133

130-
private void validateStoreCategory(String storeCategory) {
131-
if (storeCategory == null || storeCategory.isBlank()) {
134+
private void validateStoreCategory(StoreCategory storeCategory) {
135+
if (storeCategory == null) {
132136
throw new BusinessException(BusinessErrorCode.INVALID_STORE_CATEGORY);
133137
}
134138
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ public enum BusinessErrorCode {
2626
// Cheer
2727
INVALID_CHEER_DESCRIPTION("CHE001", "응원 메시지는 필수입니다."),
2828
INVALID_CHEER_IMAGE_KEY("CHE002", "응원 이미지 키가 비어 있습니다.", HttpStatus.INTERNAL_SERVER_ERROR),
29+
FULL_CHEER_SIZE_PER_MEMBER("CHE003", "회원당 응원 한도가 넘었습니다."),
30+
ALREADY_CHEERED("CHE004", "이미 응원한 가게입니다."),
2931

3032
// Map
3133
MAP_SERVER_ERROR("MAP001", "지도 서버와의 통신 오류입니다.", HttpStatus.INTERNAL_SERVER_ERROR),

src/main/java/eatda/repository/store/CheerRepository.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package eatda.repository.store;
22

3+
import eatda.domain.member.Member;
34
import eatda.domain.store.Cheer;
45
import eatda.domain.store.Store;
56
import java.util.List;
@@ -15,9 +16,13 @@ public interface CheerRepository extends Repository<Cheer, Long> {
1516
List<Cheer> findAllByOrderByCreatedAtDesc(Pageable pageable);
1617

1718
@Query("""
18-
SELECT c.imageKey FROM Cheer c
19-
WHERE c.store = :store AND c.imageKey IS NOT NULL
20-
ORDER BY c.createdAt DESC
21-
LIMIT 1""")
19+
SELECT c.imageKey FROM Cheer c
20+
WHERE c.store = :store AND c.imageKey IS NOT NULL
21+
ORDER BY c.createdAt DESC
22+
LIMIT 1""")
2223
Optional<String> findRecentImageKey(Store store);
24+
25+
int countByMember(Member member);
26+
27+
boolean existsByMemberAndStoreKakaoId(Member member, String storeKakaoId);
2328
}

0 commit comments

Comments
 (0)