Skip to content

Commit

Permalink
feat: 유저 모임 참여 기능 구현 (#34)
Browse files Browse the repository at this point in the history
* feat: 유저가 Meeting에 참여한다.

- Collection List -> Set 변경

* feat: 종료된 모임에 참여할 수 없도록 예외 추가

* test: 모임 참여에 대한 테스트 작성

- 정상적인 동작 테스트
- 종료된 모임에 대한 예외 테스트
- 최대 인원이 초과된 예외 테스트
- 이미 참여한 모임에 대한 예외 테스트

* feat: 유저 정보 가져오는 방식 수정

+ 테스트 수정
  • Loading branch information
ddingmin authored Jan 7, 2024
1 parent 836166d commit be0aa7e
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import lombok.RequiredArgsConstructor;
import net.teumteum.core.error.ErrorResponse;
import net.teumteum.core.security.service.SecurityService;
import net.teumteum.meeting.domain.Topic;
import net.teumteum.meeting.domain.response.MeetingResponse;
import net.teumteum.meeting.domain.response.MeetingsResponse;
Expand All @@ -18,6 +19,8 @@ public class MeetingController {

private final MeetingService meetingService;

private final SecurityService securityService;

@GetMapping("/{meetingId}")
@ResponseStatus(HttpStatus.OK)
public MeetingResponse getMeetingById(@PathVariable("meetingId") Long meetingId) {
Expand All @@ -36,6 +39,13 @@ public PageDto<MeetingsResponse> getMeetingsOrderByDate(Pageable pageable,
return meetingService.getMeetingsBySpecification(pageable, topic, meetingAreaStreet, participantUserId, searchWord, isOpen);
}

@PostMapping("/{meetingId}/participants")
@ResponseStatus(HttpStatus.CREATED)
public MeetingResponse addParticipant(@PathVariable("meetingId") Long meetingId) {
Long userId = securityService.getCurrentUserId();
return meetingService.addParticipant(meetingId, userId);
}

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(IllegalArgumentException.class)
public ErrorResponse handleIllegalArgumentException(IllegalArgumentException illegalArgumentException) {
Expand Down
25 changes: 21 additions & 4 deletions src/main/java/net/teumteum/meeting/domain/Meeting.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import org.springframework.util.Assert;

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

@Entity
@Getter
Expand All @@ -29,7 +29,7 @@ public class Meeting extends TimeBaseEntity {
private Long hostUserId;

@ElementCollection(fetch = FetchType.EAGER)
private List<Long> participantUserIds = new ArrayList<>();
private Set<Long> participantUserIds = new HashSet<>();

@Column(name = "topic")
@Enumerated(EnumType.STRING)
Expand All @@ -48,7 +48,20 @@ public class Meeting extends TimeBaseEntity {
private LocalDateTime promiseDateTime;

@ElementCollection(fetch = FetchType.EAGER)
private List<String> imageUrls = new ArrayList<>();
private Set<String> imageUrls = new HashSet<>();

public void addParticipant(Long userId) {
assertParticipantUserIds();
participantUserIds.add(userId);
}

public boolean alreadyParticipant(Long userId) {
return participantUserIds.contains(userId);
}

public boolean isOpen() {
return promiseDateTime.isAfter(LocalDateTime.now());
}

@PrePersist
private void assertField() {
Expand All @@ -69,4 +82,8 @@ private void assertTitle() {
Assert.isTrue(title.length() >= 2 && title.length() <= 32, "모임 제목은 2자 ~ 32자 사이가 되어야 합니다. [현재 입력된 모임 제목] : " + title);
}

private void assertParticipantUserIds() {
Assert.isTrue(participantUserIds.size() + 1 <= numberOfRecruits, "최대 참여자 수에 도달한 모임에 참여할 수 없습니다." + "[최대 참여자 수] : " + numberOfRecruits + "[현재 참여자 수] : " + participantUserIds.size());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@
import net.teumteum.meeting.domain.Topic;

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

public record MeetingResponse(
Long id,
Long hostId,
Topic topic,
String title,
String introduction,
List<String> photoUrls,
Set<String> photoUrls,
LocalDateTime promiseDateTime,
int numberOfRecruits,
MeetingArea meetingArea,
List<Long> participantIds
Set<Long> participantIds
) {
public static MeetingResponse of(
Meeting meeting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

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

public record MeetingsResponse(
List<MeetingResponse> meetings
Expand All @@ -23,11 +24,11 @@ public record MeetingResponse(
Topic topic,
String title,
String introduction,
List<String> photoUrls,
Set<String> photoUrls,
LocalDateTime promiseDateTime,
int numberOfRecruits,
MeetingArea meetingArea,
List<Long> participantIds
Set<Long> participantIds
) {
public static MeetingResponse of(
Meeting meeting
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/net/teumteum/meeting/service/MeetingService.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,20 @@ else if (searchWord != null) {
return PageDto.of(MeetingsResponse.of(meetings.getContent()), meetings.hasNext());
}

@Transactional
public MeetingResponse addParticipant(Long meetingId, Long userId) {
var existMeeting = meetingRepository.findById(meetingId)
.orElseThrow(() -> new IllegalArgumentException("meetingId에 해당하는 모임을 찾을 수 없습니다. \"" + meetingId + "\""));

if (existMeeting.alreadyParticipant(userId)) {
throw new IllegalArgumentException("이미 참여한 모임입니다.");
}

if (!existMeeting.isOpen()) {
throw new IllegalArgumentException("모임 참여 기간이 종료되었습니다.");
}

existMeeting.addParticipant(userId);
return MeetingResponse.of(existMeeting);
}
}
8 changes: 8 additions & 0 deletions src/test/java/net/teumteum/integration/Api.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,12 @@ ResponseSpec getMeetingsByTopic(String token, Pageable pageable, boolean isOpen,
.header(HttpHeaders.AUTHORIZATION, token)
.exchange();
}

ResponseSpec joinMeeting(String token, Long meetingId) {
return webTestClient.post()
.uri("/meetings/" + meetingId + "/participants")
.header(HttpHeaders.AUTHORIZATION, token)
.exchange();
}

}
Loading

0 comments on commit be0aa7e

Please sign in to comment.