Skip to content
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 @@ -5,7 +5,9 @@
import com.somemore.global.common.event.ServerEvent;
import com.somemore.global.common.event.ServerEventType;
import com.somemore.notification.domain.NotificationSubType;
import com.somemore.recruitboard.domain.RecruitBoard;
import com.somemore.volunteerapply.domain.ApplyStatus;
import com.somemore.volunteerapply.domain.VolunteerApply;
import lombok.Getter;
import lombok.experimental.SuperBuilder;

Expand Down Expand Up @@ -40,4 +42,18 @@ public VolunteerApplyStatusChangeEvent(
this.oldStatus = oldStatus;
this.newStatus = newStatus;
}

public static VolunteerApplyStatusChangeEvent from(VolunteerApply apply, RecruitBoard recruitBoard, ApplyStatus oldStatus) {

return VolunteerApplyStatusChangeEvent.builder()
.type(ServerEventType.NOTIFICATION)
.subType(NotificationSubType.VOLUNTEER_APPLY_STATUS_CHANGE)
.volunteerId(apply.getVolunteerId())
.volunteerApplyId(apply.getId())
.centerId(recruitBoard.getCenterId())
.recruitBoardId(recruitBoard.getId())
.oldStatus(oldStatus)
.newStatus(apply.getStatus())
.build();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package com.somemore.volunteerapply.service;

import com.somemore.global.common.event.ServerEventPublisher;
import com.somemore.global.common.event.ServerEventType;
import com.somemore.global.exception.BadRequestException;
import com.somemore.notification.domain.NotificationSubType;
import com.somemore.recruitboard.domain.RecruitBoard;
import com.somemore.recruitboard.usecase.query.RecruitBoardQueryUseCase;
import com.somemore.volunteerapply.domain.ApplyStatus;
import com.somemore.volunteerapply.domain.VolunteerApply;
import com.somemore.volunteerapply.event.VolunteerApplyStatusChangeEvent;
import com.somemore.volunteerapply.repository.VolunteerApplyRepository;
import com.somemore.volunteerapply.usecase.ApproveVolunteerApplyUseCase;
import com.somemore.volunteerapply.usecase.RejectVolunteerApplyUseCase;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -21,26 +20,36 @@
import static com.somemore.global.exception.ExceptionMessage.RECRUIT_BOARD_ALREADY_COMPLETED;
import static com.somemore.global.exception.ExceptionMessage.UNAUTHORIZED_RECRUIT_BOARD;
import static com.somemore.volunteerapply.domain.ApplyStatus.APPROVED;
import static com.somemore.volunteerapply.domain.ApplyStatus.REJECTED;

@RequiredArgsConstructor
@Transactional
@Service
public class ApproveVolunteerApplyService implements ApproveVolunteerApplyUseCase {
public class VolunteerApplyStatusChangeService implements ApproveVolunteerApplyUseCase, RejectVolunteerApplyUseCase {

private final VolunteerApplyRepository volunteerApplyRepository;
private final RecruitBoardQueryUseCase recruitBoardQueryUseCase;
private final ServerEventPublisher serverEventPublisher;

@Override
public void approve(Long id, UUID centerId) {
changeApplyStatus(id, centerId, APPROVED);
}

@Override
public void reject(Long id, UUID centerId) {
changeApplyStatus(id, centerId, REJECTED);
}

private void changeApplyStatus(Long id, UUID centerId, ApplyStatus newStatus) {
VolunteerApply apply = getVolunteerApply(id);
RecruitBoard recruitBoard = recruitBoardQueryUseCase.getById(apply.getRecruitBoardId());

validateWriter(recruitBoard, centerId);
validateBoardStatus(recruitBoard);

ApplyStatus oldStatus = apply.getStatus();
apply.changeStatus(APPROVED);
apply.changeStatus(newStatus);
volunteerApplyRepository.save(apply);

publishVolunteerApplyStatusChangeEvent(apply, recruitBoard, oldStatus);
Expand All @@ -65,18 +74,12 @@ private void validateBoardStatus(RecruitBoard recruitBoard) {
}
}

private void publishVolunteerApplyStatusChangeEvent(VolunteerApply apply, RecruitBoard recruitBoard, ApplyStatus oldStatus) {
VolunteerApplyStatusChangeEvent event = VolunteerApplyStatusChangeEvent.builder()
.type(ServerEventType.NOTIFICATION)
.subType(NotificationSubType.VOLUNTEER_APPLY_STATUS_CHANGE)
.volunteerId(apply.getVolunteerId())
.volunteerApplyId(apply.getId())
.centerId(recruitBoard.getCenterId())
.recruitBoardId(recruitBoard.getId())
.oldStatus(oldStatus)
.newStatus(apply.getStatus())
.build();

serverEventPublisher.publish(event);
private void publishVolunteerApplyStatusChangeEvent(VolunteerApply apply,
RecruitBoard recruitBoard,
ApplyStatus oldStatus) {
if (apply.getStatus() == oldStatus) {
return;
}
serverEventPublisher.publish(VolunteerApplyStatusChangeEvent.from(apply, recruitBoard, oldStatus));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import org.springframework.transaction.annotation.Transactional;

@Transactional
class ApplyVolunteerApplyServiceTest extends IntegrationTestSupport {
class ApplyVolunteerApplyStatusChangeServiceTest extends IntegrationTestSupport {

@Autowired
private ApplyVolunteerApplyService volunteerApplyCommandService;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,65 @@
package com.somemore.volunteerapply.service;

import static com.somemore.common.fixture.RecruitBoardFixture.createCompletedRecruitBoard;
import static com.somemore.common.fixture.RecruitBoardFixture.createRecruitBoard;
import static com.somemore.global.exception.ExceptionMessage.UNAUTHORIZED_RECRUIT_BOARD;
import static com.somemore.recruitboard.domain.VolunteerCategory.OTHER;
import static com.somemore.volunteerapply.domain.ApplyStatus.APPROVED;
import static com.somemore.volunteerapply.domain.ApplyStatus.WAITING;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import com.somemore.IntegrationTestSupport;
import com.somemore.global.common.event.ServerEventPublisher;
import com.somemore.global.exception.BadRequestException;
import com.somemore.global.exception.ExceptionMessage;
import com.somemore.recruitboard.domain.RecruitBoard;
import com.somemore.recruitboard.repository.RecruitBoardRepository;
import com.somemore.recruitboard.usecase.query.RecruitBoardQueryUseCase;
import com.somemore.volunteerapply.domain.VolunteerApply;
import com.somemore.volunteerapply.event.VolunteerApplyStatusChangeEvent;
import com.somemore.volunteerapply.repository.VolunteerApplyRepository;
import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.UUID;

import static com.somemore.common.fixture.RecruitBoardFixture.createCompletedRecruitBoard;
import static com.somemore.common.fixture.RecruitBoardFixture.createRecruitBoard;
import static com.somemore.global.exception.ExceptionMessage.UNAUTHORIZED_RECRUIT_BOARD;
import static com.somemore.recruitboard.domain.VolunteerCategory.OTHER;
import static com.somemore.volunteerapply.domain.ApplyStatus.APPROVED;
import static com.somemore.volunteerapply.domain.ApplyStatus.WAITING;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

@Transactional
class ApproveVolunteerApplyServiceTest extends IntegrationTestSupport {
class ApproveVolunteerApplyStatusChangeServiceTest extends IntegrationTestSupport {

@Autowired
private ApproveVolunteerApplyService approveVolunteerApplyService;
private VolunteerApplyStatusChangeService volunteerApplyStatusChangeService;

@Autowired
private VolunteerApplyRepository volunteerApplyRepository;

@Autowired
private RecruitBoardRepository recruitBoardRepository;

@Autowired
private RecruitBoardQueryUseCase recruitBoardQueryUseCase;


ServerEventPublisher serverEventPublisher;

@BeforeEach
void setUp() {
serverEventPublisher = mock(ServerEventPublisher.class);
volunteerApplyStatusChangeService = new VolunteerApplyStatusChangeService(
volunteerApplyRepository,
recruitBoardQueryUseCase,
serverEventPublisher
);
}

@DisplayName("봉사 지원을 승인할 수 있다.")
@Test
void approve() {
Expand All @@ -47,7 +73,7 @@ void approve() {
volunteerApplyRepository.save(apply);

// when
approveVolunteerApplyService.approve(apply.getId(), centerId);
volunteerApplyStatusChangeService.approve(apply.getId(), centerId);

// then
VolunteerApply approve = volunteerApplyRepository.findById(apply.getId()).orElseThrow();
Expand All @@ -71,7 +97,7 @@ void approveWithWrongCenter() {
// when
// then
assertThatThrownBy(
() -> approveVolunteerApplyService.approve(id, wrongCenterId)
() -> volunteerApplyStatusChangeService.approve(id, wrongCenterId)
).isInstanceOf(BadRequestException.class)
.hasMessage(UNAUTHORIZED_RECRUIT_BOARD.getMessage());
}
Expand All @@ -91,11 +117,57 @@ void approveWithAlreadyCompletedRecruit() {
// when
// then
assertThatThrownBy(
() -> approveVolunteerApplyService.approve(id, centerId)
() -> volunteerApplyStatusChangeService.approve(id, centerId)
).isInstanceOf(BadRequestException.class)
.hasMessage(ExceptionMessage.RECRUIT_BOARD_ALREADY_COMPLETED.getMessage());
}

@DisplayName("지원 상태가 변경되지 않은 경우 이벤트 퍼블리셔가 호출되지 않는다.")
@Test
void approveWithSameStatusDoesNotPublishEvent() {
// given
UUID centerId = UUID.randomUUID();

RecruitBoard board = createRecruitBoard(centerId);
recruitBoardRepository.save(board);

VolunteerApply apply = createApply(board.getId());
apply.changeStatus(APPROVED);
volunteerApplyRepository.save(apply);

// when
volunteerApplyStatusChangeService.approve(apply.getId(), centerId);

// then
verify(serverEventPublisher, never()).publish(any());
VolunteerApply approvedApply = volunteerApplyRepository.findById(apply.getId()).orElseThrow();
assertThat(approvedApply.getStatus()).isEqualTo(APPROVED);
}

@DisplayName("지원 상태가 변경된 경우 이벤트 퍼블리셔가 호출된다.")
@Test
void approveWithDifferentStatusPublishesEvent() {
// given
UUID centerId = UUID.randomUUID();

RecruitBoard board = createRecruitBoard(centerId);
recruitBoardRepository.save(board);

VolunteerApply apply = createApply(board.getId());
volunteerApplyRepository.save(apply);

// when
volunteerApplyStatusChangeService.approve(apply.getId(), centerId);

// then
ArgumentCaptor<VolunteerApplyStatusChangeEvent> eventCaptor = ArgumentCaptor.forClass(VolunteerApplyStatusChangeEvent.class);
verify(serverEventPublisher, times(1)).publish(eventCaptor.capture());

VolunteerApplyStatusChangeEvent capturedEvent = eventCaptor.getValue();
assertThat(capturedEvent).isNotNull();
assertThat(capturedEvent.getVolunteerApplyId()).isEqualTo(apply.getId());
}

private VolunteerApply createApply(Long recruitBoardId) {
return VolunteerApply.builder()
.volunteerId(UUID.randomUUID())
Expand All @@ -104,5 +176,4 @@ private VolunteerApply createApply(Long recruitBoardId) {
.attended(false)
.build();
}

}
Loading
Loading