Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 유저가 참여한 모임을 취소한다. #35

Merged
merged 2 commits into from
Jan 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ public MeetingResponse addParticipant(@PathVariable("meetingId") Long meetingId)
return meetingService.addParticipant(meetingId, userId);
}

@DeleteMapping("/{meetingId}/participants")
@ResponseStatus(HttpStatus.OK)
public void deleteParticipant(@PathVariable("meetingId") Long meetingId) {
Long userId = securityService.getCurrentUserId();
meetingService.cancelParticipant(meetingId, userId);
}

@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(IllegalArgumentException.class)
public ErrorResponse handleIllegalArgumentException(IllegalArgumentException illegalArgumentException) {
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/net/teumteum/meeting/domain/Meeting.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ public void addParticipant(Long userId) {
participantUserIds.add(userId);
}

public void cancelParticipant(Long userId) {
participantUserIds.remove(userId);
}

public boolean alreadyParticipant(Long userId) {
return participantUserIds.contains(userId);
}
Expand Down Expand Up @@ -85,5 +89,4 @@ private void assertTitle() {
private void assertParticipantUserIds() {
Assert.isTrue(participantUserIds.size() + 1 <= numberOfRecruits, "최대 참여자 수에 도달한 모임에 참여할 수 없습니다." + "[최대 참여자 수] : " + numberOfRecruits + "[현재 참여자 수] : " + participantUserIds.size());
}

}
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 @@ -68,4 +68,20 @@ public MeetingResponse addParticipant(Long meetingId, Long userId) {
existMeeting.addParticipant(userId);
return MeetingResponse.of(existMeeting);
}

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

if (!existMeeting.isOpen()) {
throw new IllegalArgumentException("종료된 모임에서 참여를 취소할 수 없습니다.");
}

if (!existMeeting.alreadyParticipant(userId)) {
throw new IllegalArgumentException("참여하지 않은 모임입니다.");
}

existMeeting.cancelParticipant(userId);
}
}
6 changes: 6 additions & 0 deletions src/test/java/net/teumteum/integration/Api.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,10 @@ ResponseSpec joinMeeting(String token, Long meetingId) {
.exchange();
}

ResponseSpec cancelMeeting(String token, Long meetingId) {
return webTestClient.delete()
.uri("/meetings/" + meetingId + "/participants")
.header(HttpHeaders.AUTHORIZATION, token)
.exchange();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -252,4 +252,64 @@ void Return_400_bad_request_if_exceed_max_number_of_recruits_meeting_id_received
.expectBody(ErrorResponse.class);
}
}

@Nested
@DisplayName("미팅 참여 취소 API는")
class Cancel_meeting_api {

@Test
@DisplayName("존재하는 모임의 id가 주어지면, 모임에 참여를 취소한다.")
void Cancel_meeting_if_exist_meeting_id_received() {
// given
var me = repository.saveAndGetUser();
var meeting = repository.saveAndGetOpenMeeting();

loginContext.setUserId(me.getId());
api.joinMeeting(VALID_TOKEN, meeting.getId());
// when
var result = api.cancelMeeting(VALID_TOKEN, meeting.getId());
// then
result.expectStatus().isOk();
}

@Test
@DisplayName("참여하지 않은 모임의 id가 주어지면, 400 Bad Request를 응답한다.")
void Return_400_bad_request_if_not_joined_meeting_id_received() {
// given
var me = repository.saveAndGetUser();
var meeting = repository.saveAndGetOpenMeeting();

loginContext.setUserId(me.getId());
// when
var result = api.cancelMeeting(VALID_TOKEN, meeting.getId());
// then
Assertions.assertThat(result.expectStatus().isBadRequest()
.expectBody(ErrorResponse.class)
.returnResult()
.getResponseBody()
)
.extracting(ErrorResponse::getMessage)
.isEqualTo("참여하지 않은 모임입니다.");
}

@Test
@DisplayName("종료된 모임의 id가 주어진다면, 400 Bad Request를 응답한다.")
void Return_400_bad_request_if_closed_meeting_id_received() {
// given
var me = repository.saveAndGetUser();
var meeting = repository.saveAndGetCloseMeeting();

loginContext.setUserId(me.getId());
// when
var result = api.cancelMeeting(VALID_TOKEN, meeting.getId());
// then
Assertions.assertThat(result.expectStatus().isBadRequest()
.expectBody(ErrorResponse.class)
.returnResult()
.getResponseBody()
)
.extracting(ErrorResponse::getMessage)
.isEqualTo("종료된 모임에서 참여를 취소할 수 없습니다.");
}
}
}
Loading