diff --git a/src/main/java/ita/tinybite/domain/party/repository/PartyParticipantRepository.java b/src/main/java/ita/tinybite/domain/party/repository/PartyParticipantRepository.java index dab65e6..16a0087 100644 --- a/src/main/java/ita/tinybite/domain/party/repository/PartyParticipantRepository.java +++ b/src/main/java/ita/tinybite/domain/party/repository/PartyParticipantRepository.java @@ -68,4 +68,16 @@ long countActivePartiesByHostId( @Param("userId") Long userId, @Param("activeStatuses") List activeStatuses ); -} \ No newline at end of file + + @Query("SELECT pp FROM PartyParticipant pp " + + "JOIN FETCH pp.party p " + + "JOIN FETCH p.host " + + "WHERE pp.user.userId = :userId " + + "AND p.host.userId != :userId " + + "AND p.status = :partyStatus " + + "AND pp.status = :participantStatus") + List findActivePartiesByUserIdExcludingHost( + @Param("userId") Long userId, + @Param("partyStatus") PartyStatus partyStatus, + @Param("participantStatus") ParticipantStatus participantStatus + );} \ No newline at end of file diff --git a/src/main/java/ita/tinybite/domain/party/repository/PartyRepository.java b/src/main/java/ita/tinybite/domain/party/repository/PartyRepository.java index 12a88f0..bd22894 100644 --- a/src/main/java/ita/tinybite/domain/party/repository/PartyRepository.java +++ b/src/main/java/ita/tinybite/domain/party/repository/PartyRepository.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.Optional; +import ita.tinybite.domain.party.enums.PartyStatus; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; @@ -20,5 +21,7 @@ public interface PartyRepository extends JpaRepository { List findByPickupLocation_Place(String place); List findByPickupLocation_PlaceAndCategory(String place, PartyCategory category); + + List findByHostUserIdAndStatus(Long userId, PartyStatus partyStatus); } diff --git a/src/main/java/ita/tinybite/domain/user/controller/UserController.java b/src/main/java/ita/tinybite/domain/user/controller/UserController.java index dde518f..8d6a0c7 100644 --- a/src/main/java/ita/tinybite/domain/user/controller/UserController.java +++ b/src/main/java/ita/tinybite/domain/user/controller/UserController.java @@ -17,6 +17,7 @@ import jakarta.validation.Valid; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.ErrorResponse; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -111,19 +112,65 @@ public APIResponse validateRejoin( return success(response); } - @Operation(summary = "활성 파티 목록 조회", description = "사용자가 참여 중인 활성 파티 목록을 조회합니다.") + @Operation( + summary = "호스팅 중인 파티 목록 조회", + description = "현재 사용자가 호스트로 있는 활성 파티 목록을 조회합니다." + ) @ApiResponses({ - @ApiResponse(responseCode = "200", description = "조회 성공", - content = @Content(array = @ArraySchema(schema = @Schema(implementation = PartyCardResponse.class)))), - @ApiResponse(responseCode = "401", description = "인증 실패") + @ApiResponse( + responseCode = "200", + description = "조회 성공", + content = @Content( + array = @ArraySchema(schema = @Schema(implementation = PartyCardResponse.class)) + ) + ), + @ApiResponse( + responseCode = "401", + description = "인증 실패", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)) + ) }) - @GetMapping("/parties/active") - public ResponseEntity> getActiveParties( + @GetMapping("/parties/hosting") + public ResponseEntity> getHostingParties( @AuthenticationPrincipal Long userId) { - List response = userService.getActiveParties(userId); + List response = userService.getHostingParties(userId); return ResponseEntity.ok(response); } + @ApiResponses({ + @ApiResponse( + responseCode = "200", + description = "조회 성공", + content = @Content( + array = @ArraySchema(schema = @Schema(implementation = PartyCardResponse.class)) + ) + ), + @ApiResponse( + responseCode = "401", + description = "인증 실패", + content = @Content(schema = @Schema(implementation = ErrorResponse.class)) + ) + }) + @GetMapping("/parties/participating") + public ResponseEntity> getParticipatingParties( + @AuthenticationPrincipal Long userId) { + List response = userService.getParticipatingParties(userId); + return ResponseEntity.ok(response); + } + +// @Operation(summary = "활성 파티 목록 조회", description = "사용자가 참여 중인 활성 파티 목록을 조회합니다.") +// @ApiResponses({ +// @ApiResponse(responseCode = "200", description = "조회 성공", +// content = @Content(array = @ArraySchema(schema = @Schema(implementation = PartyCardResponse.class)))), +// @ApiResponse(responseCode = "401", description = "인증 실패") +// }) +// @GetMapping("/parties/active") +// public ResponseEntity> getActiveParties( +// @AuthenticationPrincipal Long userId) { +// List response = userService.getActiveParties(userId); +// return ResponseEntity.ok(response); +// } + @Operation(summary = "닉네임 중복 확인", description = "닉네임 사용 가능 여부를 확인합니다.") @ApiResponses({ @ApiResponse(responseCode = "200", description = "사용 가능한 닉네임"), diff --git a/src/main/java/ita/tinybite/domain/user/entity/User.java b/src/main/java/ita/tinybite/domain/user/entity/User.java index 512a598..ef435fe 100644 --- a/src/main/java/ita/tinybite/domain/user/entity/User.java +++ b/src/main/java/ita/tinybite/domain/user/entity/User.java @@ -13,6 +13,8 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; +import java.util.Random; +import java.util.UUID; @Entity @Table(name = "users") @@ -77,8 +79,13 @@ public void addTerms(List agreements) { } public void withdraw() { - this.nickname = "탈퇴한 사용자"; + String uniqueId = UUID.randomUUID().toString().substring(0, 8); + this.nickname = "탈퇴한 사용자"+ uniqueId; this.profileImage = "/images/default-profile.jpg"; + this.email = "withdrawn_" + uniqueId + "@deleted.com"; + this.phone = String.format("010-%04d-%04d", + new Random().nextInt(10000), + new Random().nextInt(10000)); this.status = UserStatus.WITHDRAW; this.withdrawAt = LocalDateTime.now(); } diff --git a/src/main/java/ita/tinybite/domain/user/service/UserService.java b/src/main/java/ita/tinybite/domain/user/service/UserService.java index 4b7f9f0..9789ae1 100644 --- a/src/main/java/ita/tinybite/domain/user/service/UserService.java +++ b/src/main/java/ita/tinybite/domain/user/service/UserService.java @@ -7,6 +7,7 @@ import ita.tinybite.domain.party.enums.ParticipantStatus; import ita.tinybite.domain.party.enums.PartyStatus; import ita.tinybite.domain.party.repository.PartyParticipantRepository; +import ita.tinybite.domain.party.repository.PartyRepository; import ita.tinybite.domain.user.dto.req.UpdateUserReqDto; import ita.tinybite.domain.user.dto.res.RejoinValidationResponse; import ita.tinybite.domain.user.dto.res.UserResDto; @@ -19,6 +20,7 @@ import ita.tinybite.global.exception.BusinessException; import ita.tinybite.global.exception.errorcode.AuthErrorCode; import ita.tinybite.global.location.LocationService; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -29,6 +31,7 @@ import java.util.stream.Collectors; @Service +@RequiredArgsConstructor @Transactional(readOnly = true) public class UserService { @@ -37,18 +40,7 @@ public class UserService { private final LocationService locationService; private final WithDrawUserRepository withDrawUserRepository; private final PartyParticipantRepository participantRepository; - - public UserService(SecurityProvider securityProvider, - UserRepository userRepository, - LocationService locationService, - PartyParticipantRepository participantRepository, - WithDrawUserRepository withDrawUserRepository) { - this.securityProvider = securityProvider; - this.userRepository = userRepository; - this.locationService = locationService; - this.participantRepository = participantRepository; - this.withDrawUserRepository = withDrawUserRepository; - } + private final PartyRepository partyRepository; public UserResDto getUser() { User user = securityProvider.getCurrentUser(); @@ -183,4 +175,36 @@ public RejoinValidationResponse validateRejoin(String email) { .build(); } + public List getHostingParties(Long userId) { + List parties = partyRepository.findByHostUserIdAndStatus( + userId, + PartyStatus.RECRUITING + ); + + return parties.stream() + .map(party -> { + int currentParticipants = participantRepository + .countByPartyIdAndStatus(party.getId(), ParticipantStatus.APPROVED); + return PartyCardResponse.from(party, currentParticipants, true, ParticipantStatus.APPROVED); + }) + .collect(Collectors.toList()); + } + + public List getParticipatingParties(Long userId) { + List participants = participantRepository + .findActivePartiesByUserIdExcludingHost( + userId, + PartyStatus.RECRUITING, + ParticipantStatus.APPROVED + ); + + return participants.stream() + .map(pp -> { + Party party = pp.getParty(); + int currentParticipants = participantRepository + .countByPartyIdAndStatus(party.getId(), ParticipantStatus.APPROVED); + return PartyCardResponse.from(party, currentParticipants, false, pp.getStatus()); + }) + .collect(Collectors.toList()); + } } \ No newline at end of file