Skip to content

Commit b39bf14

Browse files
authored
Merge pull request #157 from Wayble-Project/develop
[release] 진행상황 Main 브랜치에 반영
2 parents da5d82b + 8a57a53 commit b39bf14

File tree

16 files changed

+959
-750
lines changed

16 files changed

+959
-750
lines changed

src/main/java/com/wayble/server/direction/service/WaybleDijkstraService.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,15 @@ private List<double[]> createPolyLine(List<Long> path) {
6464
// 좌표 중복 제거 (동일 좌표가 연속될 시, 추가 X)
6565
if (edge != null && edge.geometry() != null && !edge.geometry().isEmpty()) {
6666
for (double[] coords : edge.geometry()) {
67-
deleteDuplicateCoords(polyline, coords);
67+
double[] latLon = new double[]{coords[1], coords[0]};
68+
deleteDuplicateCoords(polyline, latLon);
6869
}
6970
} else {
7071
Node fromNode = graphInit.getNodeMap().get(from);
7172
Node toNode = graphInit.getNodeMap().get(to);
7273

73-
double[] fromCoord = new double[]{fromNode.lon(), fromNode.lat()};
74-
double[] toCoord = new double[]{toNode.lon(), toNode.lat()};
74+
double[] fromCoord = new double[]{fromNode.lat(), fromNode.lon()};
75+
double[] toCoord = new double[]{toNode.lat(), toNode.lon()};
7576

7677
deleteDuplicateCoords(polyline, fromCoord);
7778
deleteDuplicateCoords(polyline, toCoord);

src/main/java/com/wayble/server/review/controller/ReviewController.java

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
import io.swagger.v3.oas.annotations.responses.ApiResponse;
1111
import io.swagger.v3.oas.annotations.responses.ApiResponses;
1212
import jakarta.validation.Valid;
13-
import jakarta.validation.constraints.Pattern;
1413
import lombok.RequiredArgsConstructor;
14+
import org.springframework.security.core.Authentication;
15+
import org.springframework.security.core.context.SecurityContextHolder;
1516
import org.springframework.web.bind.annotation.*;
1617

1718

@@ -37,12 +38,10 @@ public class ReviewController {
3738
})
3839
public CommonResponse<String> registerReview(
3940
@PathVariable Long waybleZoneId,
40-
@RequestBody @Valid ReviewRegisterDto dto,
41-
42-
// TODO: 로그인 구현 후 Authorization 헤더 필수로 변경 필요
43-
@RequestHeader(value = "Authorization", required = false) String authorizationHeader
41+
@RequestBody @Valid ReviewRegisterDto dto
4442
) {
45-
reviewService.registerReview(waybleZoneId, dto, authorizationHeader);
43+
Long userId = extractUserId(); // 토큰에서 유저 ID 추출
44+
reviewService.registerReview(waybleZoneId, userId, dto);
4645
return CommonResponse.success("리뷰가 등록되었습니다.");
4746
}
4847

@@ -58,4 +57,26 @@ public CommonResponse<List<ReviewResponseDto>> getReviews(
5857
) {
5958
return CommonResponse.success(reviewService.getReviews(waybleZoneId, sort));
6059
}
60+
61+
private Long extractUserId() {
62+
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
63+
if (auth == null) { throw new IllegalStateException("인증 정보가 없습니다."); }
64+
65+
Object p = auth.getPrincipal();
66+
if (p instanceof Long l) { return l; }
67+
if (p instanceof Integer i) { return i.longValue(); }
68+
if (p instanceof String s) {
69+
try {
70+
return Long.parseLong(s);
71+
} catch (NumberFormatException e) {
72+
throw new IllegalStateException("principal에서 userId 파싱 실패");
73+
}
74+
}
75+
try {
76+
return Long.parseLong(auth.getName());
77+
}
78+
catch (Exception e) {
79+
throw new IllegalStateException("인증 정보에서 userId를 추출할 수 없습니다.");
80+
}
81+
}
6182
}

src/main/java/com/wayble/server/review/dto/ReviewRegisterDto.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@
77

88
@Schema(description = "리뷰 등록 요청 DTO")
99
public record ReviewRegisterDto(
10-
11-
@Schema(description = "작성자 ID", example = "1")
12-
@NotNull(message = "작성자 ID는 필수입니다.")
13-
Long userId,
14-
1510
@Schema(description = "리뷰 내용", example = "뷰가 좋고 접근성이 좋은 카페예요.")
1611
@NotBlank(message = "리뷰 내용은 비어 있을 수 없습니다.")
1712
String content,

src/main/java/com/wayble/server/review/service/ReviewService.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ public class ReviewService {
3030
private final UserRepository userRepository;
3131

3232
@Transactional
33-
public void registerReview(Long zoneId, ReviewRegisterDto dto, String token) {
33+
public void registerReview(Long zoneId, Long userId, ReviewRegisterDto dto) {
3434
WaybleZone zone = waybleZoneRepository.findById(zoneId)
3535
.orElseThrow(() -> new ApplicationException(WaybleZoneErrorCase.WAYBLE_ZONE_NOT_FOUND));
3636

37-
User user = userRepository.findById(dto.userId())
37+
User user = userRepository.findById(userId)
3838
.orElseThrow(() -> new ApplicationException(UserErrorCase.USER_NOT_FOUND));
3939

4040
Review review = Review.of(user, zone, dto.content(), dto.rating());
@@ -44,14 +44,13 @@ public void registerReview(Long zoneId, ReviewRegisterDto dto, String token) {
4444
zone.updateRating(newRating);
4545
zone.addReviewCount(1);
4646

47-
if (dto.images() != null) {
47+
if (dto.images() != null && !dto.images().isEmpty()) {
4848
for (String imageUrl : dto.images()) {
4949
reviewImageRepository.save(ReviewImage.of(review, imageUrl));
5050
}
5151
}
52-
waybleZoneRepository.save(zone);
5352

54-
// visitDate 및 facilities 저장은 필요시 추가 구현
53+
waybleZoneRepository.save(zone);
5554
}
5655

5756
@Transactional(readOnly = true)

src/main/java/com/wayble/server/user/controller/UserPlaceController.java

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
package com.wayble.server.user.controller;
22

3-
import com.wayble.server.common.exception.ApplicationException;
3+
44
import com.wayble.server.common.response.CommonResponse;
5-
import com.wayble.server.user.dto.UserPlaceListResponseDto;
5+
import com.wayble.server.user.dto.UserPlaceRemoveRequestDto;
66
import com.wayble.server.user.dto.UserPlaceRequestDto;
7-
import com.wayble.server.user.exception.UserErrorCase;
7+
import com.wayble.server.user.dto.UserPlaceSummaryDto;
88
import com.wayble.server.user.service.UserPlaceService;
9+
import com.wayble.server.wayblezone.dto.WaybleZoneListResponseDto;
910
import io.swagger.v3.oas.annotations.Operation;
1011
import io.swagger.v3.oas.annotations.responses.ApiResponse;
1112
import io.swagger.v3.oas.annotations.responses.ApiResponses;
1213
import jakarta.validation.Valid;
1314
import lombok.RequiredArgsConstructor;
15+
import org.springframework.data.domain.Page;
1416
import org.springframework.security.core.Authentication;
1517
import org.springframework.security.core.context.SecurityContextHolder;
1618
import org.springframework.web.bind.annotation.*;
@@ -41,19 +43,80 @@ public CommonResponse<String> saveUserPlace(
4143
}
4244

4345
@GetMapping
46+
@Operation(summary = "내 장소 리스트 요약 조회", description = "장소 관련 목록(리스트)만 반환합니다(개수 포함).")
47+
@ApiResponses({
48+
@ApiResponse(responseCode = "200", description = "조회 성공"),
49+
@ApiResponse(responseCode = "404", description = "유저를 찾을 수 없음"),
50+
@ApiResponse(responseCode = "403", description = "권한이 없습니다.")
51+
})
52+
public CommonResponse<List<UserPlaceSummaryDto>> getMyPlaceSummaries(
53+
@RequestParam(name = "sort", defaultValue = "latest") String sort
54+
) {
55+
Long userId = extractUserId();
56+
List<UserPlaceSummaryDto> summaries = userPlaceService.getMyPlaceSummaries(userId, sort);
57+
return CommonResponse.success(summaries);
58+
}
59+
60+
61+
@GetMapping("/zones")
62+
@Operation(summary = "특정 장소 내 웨이블존 목록 조회(페이징)",
63+
description = "placeId로 해당 장소 내부의 웨이블존 카드 목록을 반환합니다. (page는 1부터 시작.)")
64+
@ApiResponses({
65+
@ApiResponse(responseCode = "200", description = "조회 성공"),
66+
@ApiResponse(responseCode = "404", description = "유저/장소를 찾을 수 없음"),
67+
@ApiResponse(responseCode = "403", description = "권한이 없습니다.")
68+
})
69+
public CommonResponse<Page<WaybleZoneListResponseDto>> getZonesInPlace(
70+
@RequestParam Long placeId,
71+
@RequestParam(defaultValue = "1") Integer page,
72+
@RequestParam(defaultValue = "20") Integer size
73+
) {
74+
Long userId = extractUserId();
75+
Page<WaybleZoneListResponseDto> zones = userPlaceService.getZonesInPlace(userId, placeId, page, size);
76+
return CommonResponse.success(zones);
77+
}
78+
79+
@DeleteMapping
4480
@Operation(
45-
summary = "내가 저장한 장소 목록 조회",
46-
description = "유저가 저장한 모든 장소 및 해당 웨이블존 정보를 조회합니다."
81+
summary = "장소에서 웨이블존 제거",
82+
description = "RequestBody로 placeId, waybleZoneId를 받아 지정한 장소에서 웨이블존을 제거합니다."
4783
)
4884
@ApiResponses({
49-
@ApiResponse(responseCode = "200", description = "장소 목록 조회 성공"),
50-
@ApiResponse(responseCode = "404", description = "해당 유저를 찾을 수 없음"),
85+
@ApiResponse(responseCode = "200", description = "제거 성공"),
86+
@ApiResponse(responseCode = "404", description = "장소 또는 매핑 정보를 찾을 수 없음"),
5187
@ApiResponse(responseCode = "403", description = "권한이 없습니다.")
5288
})
53-
public CommonResponse<List<UserPlaceListResponseDto>> getUserPlaces(
54-
) {
55-
Long userId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
56-
List<UserPlaceListResponseDto> places = userPlaceService.getUserPlaces(userId);
57-
return CommonResponse.success(places);
89+
public CommonResponse<String> removeZoneFromPlace(@RequestBody @Valid UserPlaceRemoveRequestDto request) {
90+
Long userId = extractUserId();
91+
userPlaceService.removeZoneFromPlace(userId, request.placeId(), request.waybleZoneId());
92+
return CommonResponse.success("제거되었습니다.");
93+
}
94+
95+
96+
// SecurityContext에서 userId 추출하는 로직
97+
private Long extractUserId() {
98+
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
99+
if (auth == null) {
100+
throw new IllegalStateException("인증 정보가 없습니다.");
101+
}
102+
103+
Object p = auth.getPrincipal();
104+
105+
if (p instanceof Long l) { return l; }
106+
if (p instanceof Integer i) { return i.longValue(); }
107+
if (p instanceof String s) {
108+
try {
109+
return Long.parseLong(s);
110+
} catch (NumberFormatException e) {
111+
// 숫자 변환 실패 시 출력
112+
System.err.println("Principal 문자열을 Long으로 변환할 수 없습니다: " + s);
113+
}
114+
}
115+
116+
try {
117+
return Long.parseLong(auth.getName());
118+
} catch (Exception e) {
119+
throw new IllegalStateException("인증 정보에서 userId를 추출할 수 없습니다. Principal=" + p, e);
120+
}
58121
}
59122
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.wayble.server.user.dto;
2+
3+
import jakarta.validation.constraints.NotNull;
4+
5+
public record UserPlaceRemoveRequestDto(
6+
@NotNull Long placeId,
7+
@NotNull Long waybleZoneId
8+
) {}

src/main/java/com/wayble/server/user/dto/UserPlaceRequestDto.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44

55
public record UserPlaceRequestDto(
66
@NotNull Long waybleZoneId,
7-
@NotNull String title
7+
@NotNull String title,
8+
String color
89
) {}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.wayble.server.user.dto;
2+
3+
import lombok.Builder;
4+
5+
@Builder
6+
public record UserPlaceSummaryDto(
7+
Long placeId,
8+
String title,
9+
String color,
10+
int savedCount
11+
) {}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.wayble.server.user.dto;
2+
3+
import com.wayble.server.wayblezone.dto.WaybleZoneListResponseDto;
4+
import lombok.Builder;
5+
6+
import java.util.List;
7+
8+
@Builder
9+
public record UserPlaceZonesResponseDto(
10+
Long placeId,
11+
String title,
12+
String color,
13+
int savedCount,
14+
List<WaybleZoneListResponseDto> zones
15+
) {}

src/main/java/com/wayble/server/user/entity/UserPlace.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,17 @@
66
import lombok.Builder;
77
import lombok.Getter;
88
import lombok.NoArgsConstructor;
9+
import org.hibernate.annotations.SQLDelete;
10+
import org.hibernate.annotations.SQLRestriction;
911

1012

1113
@Entity
1214
@Getter
1315
@Builder
1416
@AllArgsConstructor
1517
@NoArgsConstructor
18+
@SQLDelete(sql = "UPDATE user_place SET deleted_at = NOW() WHERE id = ?")
19+
@SQLRestriction("deleted_at IS NULL")
1620
@Table(name = "user_place") // 유져가 저장한 장소
1721
public class UserPlace extends BaseEntity {
1822

@@ -23,7 +27,21 @@ public class UserPlace extends BaseEntity {
2327
@Column(name = "title", nullable = false)
2428
private String title;
2529

30+
@Column(length = 20) @Builder.Default
31+
private String color = "GRAY"; // 배지/아이콘 색 (정확히 무슨 색이 있는지 몰라서 일단 자유 문자열 + 기본: 회색)
32+
33+
@Column(name = "saved_count", nullable = false, columnDefinition = "int default 0")
34+
@Builder.Default
35+
private int savedCount = 0; // 리스트에 담긴 웨이블존 수
36+
37+
2638
@ManyToOne(fetch = FetchType.LAZY)
2739
@JoinColumn(name = "user_id", nullable = false)
2840
private User user;
41+
42+
public void increaseCount() { this.savedCount++; }
43+
public void decreaseCount() { if (this.savedCount > 0) this.savedCount--; }
44+
45+
public void updateTitle(String title) { this.title = title; }
46+
public void updateColor(String color) { this.color = color; }
2947
}

0 commit comments

Comments
 (0)