Skip to content

Commit 4b3f39a

Browse files
authored
Merge pull request #39 from Wayble-Project/feature/seungin
[feat] 유저 장소 저장 api 구현 (충돌 해결용)
2 parents 04825ca + 3380332 commit 4b3f39a

File tree

8 files changed

+139
-3
lines changed

8 files changed

+139
-3
lines changed

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ public class ReviewController {
3838
public CommonResponse<String> registerReview(
3939
@PathVariable Long waybleZoneId,
4040
@RequestBody @Valid ReviewRegisterDto dto,
41-
@RequestHeader(value = "Authorization", required = false) String authorizationHeader // 테스트를 위해 임시로 토큰 없이도 접근하도록 설정
41+
42+
// TODO: 로그인 구현 후 Authorization 헤더 필수로 변경 필요
43+
@RequestHeader(value = "Authorization", required = false) String authorizationHeader
4244
) {
4345
reviewService.registerReview(waybleZoneId, dto, authorizationHeader);
4446
return CommonResponse.success("리뷰가 등록되었습니다.");
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.wayble.server.user.controller;
2+
3+
import com.wayble.server.common.exception.ApplicationException;
4+
import com.wayble.server.common.response.CommonResponse;
5+
import com.wayble.server.user.dto.UserPlaceRequestDto;
6+
import com.wayble.server.user.exception.UserErrorCase;
7+
import com.wayble.server.user.service.UserPlaceService;
8+
import io.swagger.v3.oas.annotations.Operation;
9+
import io.swagger.v3.oas.annotations.responses.ApiResponse;
10+
import io.swagger.v3.oas.annotations.responses.ApiResponses;
11+
import jakarta.validation.Valid;
12+
import lombok.RequiredArgsConstructor;
13+
import org.springframework.web.bind.annotation.*;
14+
15+
@RestController
16+
@RequestMapping("/api/v1/users/{userId}/places")
17+
@RequiredArgsConstructor
18+
public class UserPlaceController {
19+
20+
private final UserPlaceService userPlaceService;
21+
22+
@PostMapping
23+
@Operation(summary = "유저 장소 저장", description = "유저가 웨이블존을 장소로 저장합니다.")
24+
@ApiResponses({
25+
@ApiResponse(responseCode = "200", description = "장소 저장 성공"),
26+
@ApiResponse(responseCode = "400", description = "이미 저장한 장소입니다."),
27+
@ApiResponse(responseCode = "404", description = "해당 유저 또는 웨이블존이 존재하지 않음")
28+
})
29+
public CommonResponse<String> saveUserPlace(
30+
@PathVariable Long userId,
31+
@RequestBody @Valid UserPlaceRequestDto request,
32+
33+
// TODO: 로그인 구현 후 Authorization 헤더 필수로 변경 필요
34+
@RequestHeader(value = "Authorization", required = false) String authorizationHeader
35+
) {
36+
// Path variable과 request body의 userId 일치 여부 확인
37+
if (!userId.equals(request.userId())) {
38+
throw new ApplicationException(UserErrorCase.INVALID_USER_ID);
39+
}
40+
41+
userPlaceService.saveUserPlace(request);
42+
return CommonResponse.success("장소가 저장되었습니다.");
43+
}
44+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.wayble.server.user.dto;
2+
3+
import jakarta.validation.constraints.NotNull;
4+
5+
public record UserPlaceRequestDto(
6+
@NotNull Long userId,
7+
@NotNull Long waybleZoneId,
8+
@NotNull String title
9+
) {}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,6 @@ public class User extends BaseEntity {
5858

5959
// TODO 프로필 이미지 관련 작업 필요
6060

61-
// TODO 내가 저장한 장소 관련 작업 필요
61+
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
62+
private List<UserPlace> userPlaces = new ArrayList<>();
6263
}

src/main/java/com/wayble/server/user/exception/UserErrorCase.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
@RequiredArgsConstructor
99
public enum UserErrorCase implements ErrorCase {
1010

11-
USER_NOT_FOUND(400, 1001, "사용자를 찾을 수 없습니다.");
11+
USER_NOT_FOUND(404, 1001, "사용자를 찾을 수 없습니다."),
12+
WAYBLE_ZONE_NOT_FOUND(404, 1002, "해당 웨이블존을 찾을 수 없습니다."),
13+
PLACE_ALREADY_SAVED(400, 1003, "이미 저장한 장소입니다."),
14+
INVALID_USER_ID(400, 1004, "요청 경로의 유저 ID와 바디의 유저 ID가 일치하지 않습니다.");
1215

1316
private final Integer httpStatusCode;
1417
private final Integer errorCode;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.wayble.server.user.repository;
2+
3+
import com.wayble.server.user.entity.UserPlace;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
6+
import java.util.Optional;
7+
8+
public interface UserPlaceRepository extends JpaRepository<UserPlace, Long> {
9+
Optional<UserPlace> findByUser_IdAndTitle(Long userId, String title);
10+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.wayble.server.user.repository;
2+
3+
import com.wayble.server.user.entity.UserPlaceWaybleZoneMapping;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
6+
public interface UserPlaceWaybleZoneMappingRepository extends JpaRepository<UserPlaceWaybleZoneMapping, Long> {
7+
boolean existsByUserPlace_User_IdAndWaybleZone_Id(Long userId, Long zoneId);
8+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.wayble.server.user.service;
2+
3+
4+
import com.wayble.server.common.exception.ApplicationException;
5+
import com.wayble.server.user.dto.UserPlaceRequestDto;
6+
import com.wayble.server.user.entity.User;
7+
import com.wayble.server.user.entity.UserPlace;
8+
import com.wayble.server.user.entity.UserPlaceWaybleZoneMapping;
9+
import com.wayble.server.user.exception.UserErrorCase;
10+
import com.wayble.server.user.repository.UserPlaceRepository;
11+
import com.wayble.server.user.repository.UserPlaceWaybleZoneMappingRepository;
12+
import com.wayble.server.user.repository.UserRepository;
13+
import com.wayble.server.wayblezone.entity.WaybleZone;
14+
import com.wayble.server.wayblezone.repository.WaybleZoneRepository;
15+
import jakarta.transaction.Transactional;
16+
import lombok.RequiredArgsConstructor;
17+
import org.springframework.stereotype.Service;
18+
19+
@Service
20+
@RequiredArgsConstructor
21+
public class UserPlaceService {
22+
23+
private final UserRepository userRepository;
24+
private final WaybleZoneRepository waybleZoneRepository;
25+
private final UserPlaceRepository userPlaceRepository;
26+
private final UserPlaceWaybleZoneMappingRepository mappingRepository;
27+
28+
@Transactional
29+
public void saveUserPlace(UserPlaceRequestDto request) {
30+
// 유저 존재 확인
31+
User user = userRepository.findById(request.userId())
32+
.orElseThrow(() -> new ApplicationException(UserErrorCase.USER_NOT_FOUND));
33+
34+
// 웨이블존 존재 확인
35+
WaybleZone waybleZone = waybleZoneRepository.findById(request.waybleZoneId())
36+
.orElseThrow(() -> new ApplicationException(UserErrorCase.WAYBLE_ZONE_NOT_FOUND));
37+
38+
// 중복 저장 확인
39+
boolean alreadySaved = mappingRepository.existsByUserPlace_User_IdAndWaybleZone_Id(request.userId(), request.waybleZoneId());
40+
if (alreadySaved) {
41+
throw new ApplicationException(UserErrorCase.PLACE_ALREADY_SAVED);
42+
}
43+
44+
// 저장
45+
UserPlace userPlace = userPlaceRepository.save(
46+
UserPlace.builder()
47+
.title(request.title())
48+
.user(user)
49+
.build()
50+
);
51+
52+
mappingRepository.save(
53+
UserPlaceWaybleZoneMapping.builder()
54+
.userPlace(userPlace)
55+
.waybleZone(waybleZone)
56+
.build()
57+
);
58+
}
59+
}

0 commit comments

Comments
 (0)