Skip to content

Commit

Permalink
feat : 파티 참여 API를 추가하라
Browse files Browse the repository at this point in the history
  • Loading branch information
runasy-koonta committed May 26, 2024
1 parent f9c13de commit 2664776
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 14 deletions.
10 changes: 10 additions & 0 deletions src/main/java/meltingpot/server/domain/entity/party/Party.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import meltingpot.server.domain.entity.party.enums.PartyStatus;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Entity
@Getter
Expand Down Expand Up @@ -63,4 +65,12 @@ public class Party extends BaseEntity {
@NotNull
@Column(name = "part_max_participant", nullable = false)
private Integer partMaxParticipant;

@OneToMany(mappedBy = "party", fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
@Builder.Default
private List<PartyContent> partyContents = new ArrayList<>();

@OneToMany(mappedBy = "party", fetch = FetchType.EAGER, cascade = CascadeType.REMOVE)
@Builder.Default
private List<PartyParticipant> partyParticipants = new ArrayList<>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class PartyParticipant extends BaseEntity {
private Party party;

@NotNull
@ManyToOne(fetch = FetchType.LAZY)
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "user_id")
private Account account;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package meltingpot.server.domain.entity.party.enums;

public enum PartyStatus {
TEMP_SAVED, RECRUIT_SCHEDULED, RECRUIT_OPEN, RECRUIT_CLOSED, RUNNING, DONE,
TEMP_SAVED, CANCELED, RECRUIT_SCHEDULED, RECRUIT_OPEN, RECRUIT_CLOSED, RUNNING, DONE,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package meltingpot.server.domain.repository;

import meltingpot.server.domain.entity.party.PartyContent;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface PartyContentRepository extends JpaRepository<PartyContent, Long> {
List<PartyContent> findAllByPartyId(int partyId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package meltingpot.server.domain.repository;

import meltingpot.server.domain.entity.party.PartyParticipant;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface PartyParticipantRepository extends JpaRepository<PartyParticipant, Long> {
List<PartyParticipant> findAllByPartyId(int partyId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
import meltingpot.server.domain.entity.party.Party;
import org.springframework.data.jpa.repository.JpaRepository;

public interface PartyRepository extends JpaRepository<Party, Long> {
public interface PartyRepository extends JpaRepository<Party, Integer> {
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import lombok.RequiredArgsConstructor;
import meltingpot.server.domain.entity.Account;
import meltingpot.server.party.dto.PartyResponse;
import meltingpot.server.party.service.PartyService;
import meltingpot.server.util.CurrentUser;
import meltingpot.server.util.ResponseCode;
import meltingpot.server.util.ResponseData;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

import java.util.NoSuchElementException;

Expand All @@ -22,18 +21,32 @@
public class PartyController {
private final PartyService partyService;

// Todo: 사용자 인증 추가
@GetMapping("/{partyId}")
@Operation(summary = "파티 정보 조회", description = "파티 ID를 통해 파티 정보를 불러옵니다.")
@Operation(summary = "파티 정보 조회", description = "파티 ID를 통해 파티 정보를 불러옵니다. 임시 저장된 파티를 불러오는 경우 작성자만 불러올 수 있습니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "OK", description = "파티 정보 조회 성공"),
@ApiResponse(responseCode = "NOT_FOUND", description = "파티 정보를 찾을 수 없습니다")
})
public ResponseEntity<ResponseData<PartyResponse>> getParty(@PathVariable Long partyId) {
public ResponseEntity<ResponseData<PartyResponse>> getParty(@PathVariable int partyId, @CurrentUser Account user) {
try {
return ResponseData.toResponseEntity(ResponseCode.PARTY_FETCH_SUCCESS, partyService.getParty(partyId));
return ResponseData.toResponseEntity(ResponseCode.PARTY_FETCH_SUCCESS, partyService.getParty(partyId, user));
} catch (NoSuchElementException e) {
return ResponseData.toResponseEntity(ResponseCode.PARTY_NOT_FOUND, null);
}
}

@PostMapping("/{partyId}/join")
@Operation(summary = "파티 참여", description = "파티 ID를 통해 특정 파티에 참여")
@ApiResponses(value = {
@ApiResponse(responseCode = "OK", description = "파티 참여 성공"),
@ApiResponse(responseCode = "NOT_FOUND", description = "파티 정보를 찾을 수 없습니다"),
@ApiResponse(responseCode = "BAD_REQUEST", description = "파티 참여 실패 (이미 참여한 파티, 최대 인원 초과, 모집중이 아닌 파티 등)")
})
public ResponseEntity<ResponseData> joinParty(@PathVariable int partyId, @CurrentUser Account user) {
try {
return ResponseData.toResponseEntity(partyService.joinParty(partyId, user));
} catch (NoSuchElementException e) {
return ResponseData.toResponseEntity(ResponseCode.PARTY_NOT_FOUND);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package meltingpot.server.party.dto;

import lombok.Builder;
import meltingpot.server.domain.entity.party.PartyContent;

@Builder
public record PartyContentResponse(
String lang,
String content
) {
public static PartyContentResponse of(PartyContent partyContent) {
return PartyContentResponse.builder()
.lang(partyContent.getPartyContentLang())
.content(partyContent.getPartyContent())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package meltingpot.server.party.dto;

import lombok.Builder;
import meltingpot.server.domain.entity.party.PartyParticipant;

@Builder
public record PartyParticipantResponse(
String name
) {
public static PartyParticipantResponse of(PartyParticipant partyParticipant) {
return PartyParticipantResponse.builder()
.name(partyParticipant.getAccount().getName())
.build();
}
}
8 changes: 7 additions & 1 deletion src/main/java/meltingpot/server/party/dto/PartyResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import meltingpot.server.domain.entity.party.Party;
import meltingpot.server.domain.entity.party.enums.PartyStatus;

import java.util.List;

@Builder
public record PartyResponse(
int id,
Expand All @@ -16,7 +18,9 @@ public record PartyResponse(
Boolean locationReserved,
Boolean locationCanBeChanged,
int minParticipant,
int maxParticipant
int maxParticipant,
List<PartyParticipantResponse> participants,
List<PartyContentResponse> contents
) {
public static PartyResponse of(Party party) {
return PartyResponse.builder().id(party.getId())
Expand All @@ -30,6 +34,8 @@ public static PartyResponse of(Party party) {
.locationCanBeChanged(party.getPartyLocationCanBeChanged())
.minParticipant(party.getPartyMinParticipant())
.maxParticipant(party.getPartyMinParticipant())
.participants(party.getPartyParticipants().stream().map(PartyParticipantResponse::of).toList())
.contents(party.getPartyContents().stream().map(PartyContentResponse::of).toList())
.build();
}
}
52 changes: 50 additions & 2 deletions src/main/java/meltingpot/server/party/service/PartyService.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,67 @@
package meltingpot.server.party.service;

import lombok.RequiredArgsConstructor;
import meltingpot.server.domain.entity.Account;
import meltingpot.server.domain.entity.party.PartyParticipant;
import meltingpot.server.domain.entity.party.enums.ParticipantStatus;
import meltingpot.server.domain.entity.party.enums.PartyStatus;
import meltingpot.server.domain.repository.PartyParticipantRepository;
import meltingpot.server.domain.repository.PartyRepository;
import meltingpot.server.party.dto.PartyResponse;
import meltingpot.server.util.ResponseCode;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import meltingpot.server.domain.entity.party.Party;

import java.util.List;
import java.util.NoSuchElementException;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class PartyService {
private final PartyRepository partyRepository;
private final PartyParticipantRepository partyParticipantRepository;

@Transactional
public PartyResponse getParty(int partyId, Account user) {
Party party = partyRepository.findById(partyId).orElseThrow();
PartyStatus partyStatus = party.getPartyStatus();

boolean isPartyOwner = party.getAccount().equals(user);

if ((!isPartyOwner && partyStatus == PartyStatus.TEMP_SAVED) || partyStatus == PartyStatus.CANCELED) {
throw new NoSuchElementException();
}

return PartyResponse.of(party);
}

@Transactional
public PartyResponse getParty(Long partyId) {
return partyRepository.findById(partyId).map(PartyResponse::of).orElseThrow();
public ResponseCode joinParty(int partyId, Account user) {
Party party = partyRepository.findById(partyId).orElseThrow();
PartyStatus partyStatus = party.getPartyStatus();

if (partyStatus != PartyStatus.RECRUIT_OPEN) {
return ResponseCode.PARTY_NOT_OPEN;
}

List<PartyParticipant> partyParticipants = party.getPartyParticipants().stream().filter((participant) -> participant.getParticipantStatus() != ParticipantStatus.CANCELED).toList();
if (partyParticipants.stream().anyMatch((participant) -> participant.getParticipantStatus() != ParticipantStatus.CANCELED && participant.getAccount().equals(user))) {
return ResponseCode.PARTY_ALREADY_JOINED;
}

if (partyParticipants.size() >= party.getPartyMaxParticipant()) {
return ResponseCode.PARTY_FULL;
}

PartyParticipant partyParticipant = PartyParticipant.builder()
.party(party)
.account(user)
.participantStatus(ParticipantStatus.APPROVED)
.build();
partyParticipantRepository.save(partyParticipant);

return ResponseCode.PARTY_JOIN_SUCCESS;
}
}
4 changes: 4 additions & 0 deletions src/main/java/meltingpot/server/util/ResponseCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public enum ResponseCode {
SIGNOUT_SUCCESS(OK, "로그아웃 성공"),
REISSUE_TOKEN_SUCCESS(OK, "토큰 재발급 성공"),
PARTY_FETCH_SUCCESS(OK, "파티 정보 불러오기 성공"),
PARTY_JOIN_SUCCESS(OK, "파티 참여 성공"),


/* 201 CREATED : 요청 성공, 자원 생성 */
Expand All @@ -24,6 +25,9 @@ public enum ResponseCode {
/* 400 BAD_REQUEST : 잘못된 요청 */
MAIL_SEND_FAIL(BAD_REQUEST, "메일 전송 실패"),
AUTH_NUMBER_INCORRECT(BAD_REQUEST, "인증 번호가 옳지 않습니다"),
PARTY_NOT_OPEN(BAD_REQUEST, "모집중인 파티가 아닙니다"),
PARTY_FULL(BAD_REQUEST, "파티 인원이 가득 찼습니다"),
PARTY_ALREADY_JOINED(BAD_REQUEST, "이미 참여한 파티입니다"),


/* 401 UNAUTHORIZED : 인증되지 않은 사용자 */
Expand Down

0 comments on commit 2664776

Please sign in to comment.