diff --git a/src/main/java/com/wayble/server/user/controller/UserPlaceController.java b/src/main/java/com/wayble/server/user/controller/UserPlaceController.java index 7c1388a..ac89661 100644 --- a/src/main/java/com/wayble/server/user/controller/UserPlaceController.java +++ b/src/main/java/com/wayble/server/user/controller/UserPlaceController.java @@ -55,7 +55,7 @@ public CommonResponse createPlaceList( } @GetMapping - @Operation(summary = "내 장소 리스트 요약 조회", description = "장소 관련 목록(리스트)만 반환합니다(개수 포함).") + @Operation(summary = "내가 저장한 리스트 요약 조회", description = "장소 관련 목록(리스트)만 반환합니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "조회 성공"), @ApiResponse(responseCode = "404", description = "유저를 찾을 수 없음"), @@ -69,42 +69,25 @@ public CommonResponse> getMyPlaceSummaries( return CommonResponse.success(summaries); } - @DeleteMapping - @Operation( - summary = "장소에서 웨이블존 제거", - description = "RequestBody로 placeId, waybleZoneId를 받아 지정한 장소에서 웨이블존을 제거합니다." - ) - @ApiResponses({ - @ApiResponse(responseCode = "200", description = "제거 성공"), - @ApiResponse(responseCode = "404", description = "장소 또는 매핑 정보를 찾을 수 없음"), - @ApiResponse(responseCode = "403", description = "권한이 없습니다.") - }) - public CommonResponse removeZoneFromPlace( - @Parameter(hidden = true) @CurrentUser Long userId, - @RequestBody @Valid UserPlaceRemoveRequestDto request - ) { - userPlaceService.removeZoneFromPlace(userId, request.placeId(), request.waybleZoneId()); - return CommonResponse.success("제거되었습니다."); - } @PostMapping("/zones") - @Operation(summary = "리스트에 웨이블존 추가", - description = "placeId와 waybleZoneId 배열을 받아 여러 웨이블존을 리스트에 추가합니다.") + @Operation(summary = "웨이블존에 저장한 리스트 추가 (여러 개 가능)", + description = "웨이블존에 사용자가 요청한 리스트들을 추가합니다.") @ApiResponses({ - @ApiResponse(responseCode = "200", description = "웨이블존 추가 성공"), + @ApiResponse(responseCode = "200", description = "웨이블존에 리스트 추가 성공"), @ApiResponse(responseCode = "404", description = "유저/리스트/웨이블존을 찾을 수 없음") }) - public CommonResponse addZonesToPlace( + public CommonResponse addZoneToPlaces( @Parameter(hidden = true) @CurrentUser Long userId, @RequestBody @Valid UserPlaceAddZonesRequestDto request ) { - userPlaceService.addZonesToPlace(userId, request.placeId(), request.waybleZoneIds()); - return CommonResponse.success("리스트에 웨이블존이 추가되었습니다."); + int added = userPlaceService.addZoneToPlaces(userId, request.placeIds(), request.waybleZoneId()); + return CommonResponse.success(String.format("%d개 리스트에 추가되었습니다.", added)); } @GetMapping("/zones") - @Operation(summary = "특정 장소 내 웨이블존 목록 조회(페이징)", - description = "placeId로 해당 장소 내부의 웨이블존 카드 목록을 반환합니다. (page는 0부터 시작.)") + @Operation(summary = "저장한 리스트 내 웨이블존 목록 조회(페이징)", + description = "placeId로 해당 장소 내부의 웨이블존 목록을 반환합니다. (page는 1부터 시작.)") @ApiResponses({ @ApiResponse(responseCode = "200", description = "조회 성공"), @ApiResponse(responseCode = "404", description = "유저/장소를 찾을 수 없음"), @@ -113,10 +96,28 @@ public CommonResponse addZonesToPlace( public CommonResponse> getZonesInPlace( @Parameter(hidden = true) @CurrentUser Long userId, @RequestParam Long placeId, - @RequestParam(defaultValue = "0") @Min(0) Integer page, + @RequestParam(defaultValue = "1") @Min(1) Integer page, @RequestParam(defaultValue = "20") @Min(1) @Max(100) Integer size ) { Page zones = userPlaceService.getZonesInPlace(userId, placeId, page, size); return CommonResponse.success(zones); } + + @DeleteMapping("/zones") + @Operation( + summary = "내가 저장한 리스트에서 웨이블존 제거", + description = "RequestBody로 placeId, waybleZoneId를 받아 지정한 장소에서 웨이블존을 제거합니다." + ) + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "제거 성공"), + @ApiResponse(responseCode = "404", description = "장소 또는 매핑 정보를 찾을 수 없음"), + @ApiResponse(responseCode = "403", description = "권한이 없습니다.") + }) + public CommonResponse removeZoneFromPlace( + @Parameter(hidden = true) @CurrentUser Long userId, + @RequestBody @Valid UserPlaceRemoveRequestDto request + ) { + userPlaceService.removeZoneFromPlace(userId, request.placeId(), request.waybleZoneId()); + return CommonResponse.success("성공적으로 제거되었습니다."); + } } diff --git a/src/main/java/com/wayble/server/user/dto/UserPlaceAddZonesRequestDto.java b/src/main/java/com/wayble/server/user/dto/UserPlaceAddZonesRequestDto.java index bd1524c..ae986b4 100644 --- a/src/main/java/com/wayble/server/user/dto/UserPlaceAddZonesRequestDto.java +++ b/src/main/java/com/wayble/server/user/dto/UserPlaceAddZonesRequestDto.java @@ -5,6 +5,6 @@ import java.util.List; public record UserPlaceAddZonesRequestDto( - @NotNull Long placeId, - @NotEmpty List waybleZoneIds + @NotEmpty List<@NotNull Long> placeIds, + @NotNull Long waybleZoneId ) {} diff --git a/src/main/java/com/wayble/server/user/dto/UserPlaceRequestDto.java b/src/main/java/com/wayble/server/user/dto/UserPlaceRequestDto.java deleted file mode 100644 index a265e39..0000000 --- a/src/main/java/com/wayble/server/user/dto/UserPlaceRequestDto.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.wayble.server.user.dto; - -import jakarta.validation.constraints.NotNull; - -public record UserPlaceRequestDto( - @NotNull Long waybleZoneId, - @NotNull String title, - String color -) {} diff --git a/src/main/java/com/wayble/server/user/dto/UserResponseDto.java b/src/main/java/com/wayble/server/user/dto/UserResponseDto.java deleted file mode 100644 index 7e5a712..0000000 --- a/src/main/java/com/wayble/server/user/dto/UserResponseDto.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.wayble.server.user.dto; - -public record UserResponseDto() { -} diff --git a/src/main/java/com/wayble/server/user/exception/UserErrorCase.java b/src/main/java/com/wayble/server/user/exception/UserErrorCase.java index 1d28320..4fb835a 100644 --- a/src/main/java/com/wayble/server/user/exception/UserErrorCase.java +++ b/src/main/java/com/wayble/server/user/exception/UserErrorCase.java @@ -23,7 +23,7 @@ public enum UserErrorCase implements ErrorCase { NICKNAME_DUPLICATED(409,1013, "이미 사용 중인 닉네임입니다."), PLACE_NOT_FOUND(404, 1014, "저장된 장소를 찾을 수 없습니다."), PLACE_MAPPING_NOT_FOUND(404, 1015, "해당 장소에 해당 웨이블존이 없습니다."), - PLACE_TITLE_DUPLICATED(400, 1016, "동일한 이름의 리스트가 이미 있습니다."); + PLACE_TITLE_DUPLICATED(409, 1016, "동일한 이름의 리스트가 이미 있습니다."); private final Integer httpStatusCode; private final Integer errorCode; diff --git a/src/main/java/com/wayble/server/user/service/UserPlaceService.java b/src/main/java/com/wayble/server/user/service/UserPlaceService.java index caa4d07..2be3deb 100644 --- a/src/main/java/com/wayble/server/user/service/UserPlaceService.java +++ b/src/main/java/com/wayble/server/user/service/UserPlaceService.java @@ -3,7 +3,6 @@ import com.wayble.server.common.exception.ApplicationException; import com.wayble.server.user.dto.UserPlaceCreateRequestDto; -import com.wayble.server.user.dto.UserPlaceRequestDto; import com.wayble.server.user.dto.UserPlaceSummaryDto; import com.wayble.server.user.entity.User; import com.wayble.server.user.entity.UserPlace; @@ -59,18 +58,21 @@ public Long createPlaceList(Long userId, UserPlaceCreateRequestDto request) { } @Transactional - public void addZonesToPlace(Long userId, Long placeId, List waybleZoneIds) { - UserPlace place = userPlaceRepository.findByIdAndUser_Id(placeId, userId) - .orElseThrow(() -> new ApplicationException(UserErrorCase.PLACE_NOT_FOUND)); + public int addZoneToPlaces(Long userId, List placeIds, Long waybleZoneId) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new ApplicationException(UserErrorCase.USER_NOT_FOUND)); + + WaybleZone zone = waybleZoneRepository.findById(waybleZoneId) + .orElseThrow(() -> new ApplicationException(UserErrorCase.WAYBLE_ZONE_NOT_FOUND)); - Set uniqueIds = new LinkedHashSet<>(waybleZoneIds); + Set uniquePlaceIds = new LinkedHashSet<>(placeIds); int added = 0; - for (Long zoneId : uniqueIds) { - WaybleZone zone = waybleZoneRepository.findById(zoneId) - .orElseThrow(() -> new ApplicationException(UserErrorCase.WAYBLE_ZONE_NOT_FOUND)); + for (Long placeId : uniquePlaceIds) { + UserPlace place = userPlaceRepository.findByIdAndUser_Id(placeId, user.getId()) + .orElseThrow(() -> new ApplicationException(UserErrorCase.PLACE_NOT_FOUND)); - boolean exists = mappingRepository.existsByUserPlace_IdAndWaybleZone_Id(placeId, zoneId); + boolean exists = mappingRepository.existsByUserPlace_IdAndWaybleZone_Id(placeId, waybleZoneId); if (exists) continue; mappingRepository.save(UserPlaceWaybleZoneMapping.builder() @@ -79,16 +81,18 @@ public void addZonesToPlace(Long userId, Long placeId, List waybleZoneIds) .build()); place.increaseCount(); - zone.addLikes(1); - waybleZoneRepository.save(zone); + userPlaceRepository.save(place); + zone.addLikes(1); // 리스트 하나에 추가될 때마다 +1 added++; } - if (added > 0) userPlaceRepository.save(place); + if (added > 0) { + waybleZoneRepository.save(zone); + } + return added; } - @Transactional(readOnly = true) public List getMyPlaceSummaries(Long userId, String sort) { userRepository.findById(userId) @@ -113,7 +117,7 @@ public Page getZonesInPlace(Long userId, Long placeId UserPlace place = userPlaceRepository.findByIdAndUser_Id(placeId, userId) .orElseThrow(() -> new ApplicationException(UserErrorCase.PLACE_NOT_FOUND)); - Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "id")); + Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "id")); Page zones = mappingRepository.findZonesByPlaceId(place.getId(), pageable); return zones.map(z ->