Skip to content

Commit b26fa48

Browse files
authored
Feature/219 봉사 신청 거절 알림 (#220)
* feat(VolunteerApplyStatusChangeEvent): 거절 이벤트 처리 - 이전 상태와 현 상태 비교 검증. - 중복 코드 최소화. * test(VolunteerStatusChangeEvent): 봉사상태변경이벤트 발생 검증 테스트 추가 - 이전 상태와 현 상태가 동일하다면 이벤트가 발생하지 않음. * refactor(VolunteerApplyStatusChangeService): 중복 코드 해결 - approve와 reject usecase를 한 구현체에서 해결
1 parent 404ae84 commit b26fa48

File tree

6 files changed

+214
-110
lines changed

6 files changed

+214
-110
lines changed

src/main/java/com/somemore/volunteerapply/event/VolunteerApplyStatusChangeEvent.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
import com.somemore.global.common.event.ServerEvent;
66
import com.somemore.global.common.event.ServerEventType;
77
import com.somemore.notification.domain.NotificationSubType;
8+
import com.somemore.recruitboard.domain.RecruitBoard;
89
import com.somemore.volunteerapply.domain.ApplyStatus;
10+
import com.somemore.volunteerapply.domain.VolunteerApply;
911
import lombok.Getter;
1012
import lombok.experimental.SuperBuilder;
1113

@@ -40,4 +42,18 @@ public VolunteerApplyStatusChangeEvent(
4042
this.oldStatus = oldStatus;
4143
this.newStatus = newStatus;
4244
}
45+
46+
public static VolunteerApplyStatusChangeEvent from(VolunteerApply apply, RecruitBoard recruitBoard, ApplyStatus oldStatus) {
47+
48+
return VolunteerApplyStatusChangeEvent.builder()
49+
.type(ServerEventType.NOTIFICATION)
50+
.subType(NotificationSubType.VOLUNTEER_APPLY_STATUS_CHANGE)
51+
.volunteerId(apply.getVolunteerId())
52+
.volunteerApplyId(apply.getId())
53+
.centerId(recruitBoard.getCenterId())
54+
.recruitBoardId(recruitBoard.getId())
55+
.oldStatus(oldStatus)
56+
.newStatus(apply.getStatus())
57+
.build();
58+
}
4359
}

src/main/java/com/somemore/volunteerapply/service/RejectVolunteerApplyService.java

Lines changed: 0 additions & 58 deletions
This file was deleted.

src/main/java/com/somemore/volunteerapply/service/ApproveVolunteerApplyService.java renamed to src/main/java/com/somemore/volunteerapply/service/VolunteerApplyStatusChangeService.java

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
package com.somemore.volunteerapply.service;
22

33
import com.somemore.global.common.event.ServerEventPublisher;
4-
import com.somemore.global.common.event.ServerEventType;
54
import com.somemore.global.exception.BadRequestException;
6-
import com.somemore.notification.domain.NotificationSubType;
75
import com.somemore.recruitboard.domain.RecruitBoard;
86
import com.somemore.recruitboard.usecase.query.RecruitBoardQueryUseCase;
97
import com.somemore.volunteerapply.domain.ApplyStatus;
108
import com.somemore.volunteerapply.domain.VolunteerApply;
119
import com.somemore.volunteerapply.event.VolunteerApplyStatusChangeEvent;
1210
import com.somemore.volunteerapply.repository.VolunteerApplyRepository;
1311
import com.somemore.volunteerapply.usecase.ApproveVolunteerApplyUseCase;
12+
import com.somemore.volunteerapply.usecase.RejectVolunteerApplyUseCase;
1413
import lombok.RequiredArgsConstructor;
1514
import org.springframework.stereotype.Service;
1615
import org.springframework.transaction.annotation.Transactional;
@@ -21,26 +20,36 @@
2120
import static com.somemore.global.exception.ExceptionMessage.RECRUIT_BOARD_ALREADY_COMPLETED;
2221
import static com.somemore.global.exception.ExceptionMessage.UNAUTHORIZED_RECRUIT_BOARD;
2322
import static com.somemore.volunteerapply.domain.ApplyStatus.APPROVED;
23+
import static com.somemore.volunteerapply.domain.ApplyStatus.REJECTED;
2424

2525
@RequiredArgsConstructor
2626
@Transactional
2727
@Service
28-
public class ApproveVolunteerApplyService implements ApproveVolunteerApplyUseCase {
28+
public class VolunteerApplyStatusChangeService implements ApproveVolunteerApplyUseCase, RejectVolunteerApplyUseCase {
2929

3030
private final VolunteerApplyRepository volunteerApplyRepository;
3131
private final RecruitBoardQueryUseCase recruitBoardQueryUseCase;
3232
private final ServerEventPublisher serverEventPublisher;
3333

3434
@Override
3535
public void approve(Long id, UUID centerId) {
36+
changeApplyStatus(id, centerId, APPROVED);
37+
}
38+
39+
@Override
40+
public void reject(Long id, UUID centerId) {
41+
changeApplyStatus(id, centerId, REJECTED);
42+
}
43+
44+
private void changeApplyStatus(Long id, UUID centerId, ApplyStatus newStatus) {
3645
VolunteerApply apply = getVolunteerApply(id);
3746
RecruitBoard recruitBoard = recruitBoardQueryUseCase.getById(apply.getRecruitBoardId());
3847

3948
validateWriter(recruitBoard, centerId);
4049
validateBoardStatus(recruitBoard);
4150

4251
ApplyStatus oldStatus = apply.getStatus();
43-
apply.changeStatus(APPROVED);
52+
apply.changeStatus(newStatus);
4453
volunteerApplyRepository.save(apply);
4554

4655
publishVolunteerApplyStatusChangeEvent(apply, recruitBoard, oldStatus);
@@ -65,18 +74,12 @@ private void validateBoardStatus(RecruitBoard recruitBoard) {
6574
}
6675
}
6776

68-
private void publishVolunteerApplyStatusChangeEvent(VolunteerApply apply, RecruitBoard recruitBoard, ApplyStatus oldStatus) {
69-
VolunteerApplyStatusChangeEvent event = VolunteerApplyStatusChangeEvent.builder()
70-
.type(ServerEventType.NOTIFICATION)
71-
.subType(NotificationSubType.VOLUNTEER_APPLY_STATUS_CHANGE)
72-
.volunteerId(apply.getVolunteerId())
73-
.volunteerApplyId(apply.getId())
74-
.centerId(recruitBoard.getCenterId())
75-
.recruitBoardId(recruitBoard.getId())
76-
.oldStatus(oldStatus)
77-
.newStatus(apply.getStatus())
78-
.build();
79-
80-
serverEventPublisher.publish(event);
77+
private void publishVolunteerApplyStatusChangeEvent(VolunteerApply apply,
78+
RecruitBoard recruitBoard,
79+
ApplyStatus oldStatus) {
80+
if (apply.getStatus() == oldStatus) {
81+
return;
82+
}
83+
serverEventPublisher.publish(VolunteerApplyStatusChangeEvent.from(apply, recruitBoard, oldStatus));
8184
}
82-
}
85+
}

src/test/java/com/somemore/volunteerapply/service/ApplyVolunteerApplyServiceTest.java renamed to src/test/java/com/somemore/volunteerapply/service/ApplyVolunteerApplyStatusChangeServiceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import org.springframework.transaction.annotation.Transactional;
2323

2424
@Transactional
25-
class ApplyVolunteerApplyServiceTest extends IntegrationTestSupport {
25+
class ApplyVolunteerApplyStatusChangeServiceTest extends IntegrationTestSupport {
2626

2727
@Autowired
2828
private ApplyVolunteerApplyService volunteerApplyCommandService;

src/test/java/com/somemore/volunteerapply/service/ApproveVolunteerApplyServiceTest.java renamed to src/test/java/com/somemore/volunteerapply/service/ApproveVolunteerApplyStatusChangeServiceTest.java

Lines changed: 88 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,65 @@
11
package com.somemore.volunteerapply.service;
22

3-
import static com.somemore.common.fixture.RecruitBoardFixture.createCompletedRecruitBoard;
4-
import static com.somemore.common.fixture.RecruitBoardFixture.createRecruitBoard;
5-
import static com.somemore.global.exception.ExceptionMessage.UNAUTHORIZED_RECRUIT_BOARD;
6-
import static com.somemore.recruitboard.domain.VolunteerCategory.OTHER;
7-
import static com.somemore.volunteerapply.domain.ApplyStatus.APPROVED;
8-
import static com.somemore.volunteerapply.domain.ApplyStatus.WAITING;
9-
import static org.assertj.core.api.Assertions.assertThat;
10-
import static org.assertj.core.api.Assertions.assertThatThrownBy;
11-
123
import com.somemore.IntegrationTestSupport;
4+
import com.somemore.global.common.event.ServerEventPublisher;
135
import com.somemore.global.exception.BadRequestException;
146
import com.somemore.global.exception.ExceptionMessage;
157
import com.somemore.recruitboard.domain.RecruitBoard;
168
import com.somemore.recruitboard.repository.RecruitBoardRepository;
9+
import com.somemore.recruitboard.usecase.query.RecruitBoardQueryUseCase;
1710
import com.somemore.volunteerapply.domain.VolunteerApply;
11+
import com.somemore.volunteerapply.event.VolunteerApplyStatusChangeEvent;
1812
import com.somemore.volunteerapply.repository.VolunteerApplyRepository;
19-
import java.util.UUID;
13+
import org.junit.jupiter.api.BeforeEach;
2014
import org.junit.jupiter.api.DisplayName;
2115
import org.junit.jupiter.api.Test;
16+
import org.mockito.ArgumentCaptor;
2217
import org.springframework.beans.factory.annotation.Autowired;
2318
import org.springframework.transaction.annotation.Transactional;
2419

20+
import java.util.UUID;
21+
22+
import static com.somemore.common.fixture.RecruitBoardFixture.createCompletedRecruitBoard;
23+
import static com.somemore.common.fixture.RecruitBoardFixture.createRecruitBoard;
24+
import static com.somemore.global.exception.ExceptionMessage.UNAUTHORIZED_RECRUIT_BOARD;
25+
import static com.somemore.recruitboard.domain.VolunteerCategory.OTHER;
26+
import static com.somemore.volunteerapply.domain.ApplyStatus.APPROVED;
27+
import static com.somemore.volunteerapply.domain.ApplyStatus.WAITING;
28+
import static org.assertj.core.api.Assertions.assertThat;
29+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
30+
import static org.mockito.ArgumentMatchers.any;
31+
import static org.mockito.Mockito.mock;
32+
import static org.mockito.Mockito.never;
33+
import static org.mockito.Mockito.times;
34+
import static org.mockito.Mockito.verify;
35+
2536
@Transactional
26-
class ApproveVolunteerApplyServiceTest extends IntegrationTestSupport {
37+
class ApproveVolunteerApplyStatusChangeServiceTest extends IntegrationTestSupport {
2738

28-
@Autowired
29-
private ApproveVolunteerApplyService approveVolunteerApplyService;
39+
private VolunteerApplyStatusChangeService volunteerApplyStatusChangeService;
3040

3141
@Autowired
3242
private VolunteerApplyRepository volunteerApplyRepository;
3343

3444
@Autowired
3545
private RecruitBoardRepository recruitBoardRepository;
3646

47+
@Autowired
48+
private RecruitBoardQueryUseCase recruitBoardQueryUseCase;
49+
50+
51+
ServerEventPublisher serverEventPublisher;
52+
53+
@BeforeEach
54+
void setUp() {
55+
serverEventPublisher = mock(ServerEventPublisher.class);
56+
volunteerApplyStatusChangeService = new VolunteerApplyStatusChangeService(
57+
volunteerApplyRepository,
58+
recruitBoardQueryUseCase,
59+
serverEventPublisher
60+
);
61+
}
62+
3763
@DisplayName("봉사 지원을 승인할 수 있다.")
3864
@Test
3965
void approve() {
@@ -47,7 +73,7 @@ void approve() {
4773
volunteerApplyRepository.save(apply);
4874

4975
// when
50-
approveVolunteerApplyService.approve(apply.getId(), centerId);
76+
volunteerApplyStatusChangeService.approve(apply.getId(), centerId);
5177

5278
// then
5379
VolunteerApply approve = volunteerApplyRepository.findById(apply.getId()).orElseThrow();
@@ -71,7 +97,7 @@ void approveWithWrongCenter() {
7197
// when
7298
// then
7399
assertThatThrownBy(
74-
() -> approveVolunteerApplyService.approve(id, wrongCenterId)
100+
() -> volunteerApplyStatusChangeService.approve(id, wrongCenterId)
75101
).isInstanceOf(BadRequestException.class)
76102
.hasMessage(UNAUTHORIZED_RECRUIT_BOARD.getMessage());
77103
}
@@ -91,11 +117,57 @@ void approveWithAlreadyCompletedRecruit() {
91117
// when
92118
// then
93119
assertThatThrownBy(
94-
() -> approveVolunteerApplyService.approve(id, centerId)
120+
() -> volunteerApplyStatusChangeService.approve(id, centerId)
95121
).isInstanceOf(BadRequestException.class)
96122
.hasMessage(ExceptionMessage.RECRUIT_BOARD_ALREADY_COMPLETED.getMessage());
97123
}
98124

125+
@DisplayName("지원 상태가 변경되지 않은 경우 이벤트 퍼블리셔가 호출되지 않는다.")
126+
@Test
127+
void approveWithSameStatusDoesNotPublishEvent() {
128+
// given
129+
UUID centerId = UUID.randomUUID();
130+
131+
RecruitBoard board = createRecruitBoard(centerId);
132+
recruitBoardRepository.save(board);
133+
134+
VolunteerApply apply = createApply(board.getId());
135+
apply.changeStatus(APPROVED);
136+
volunteerApplyRepository.save(apply);
137+
138+
// when
139+
volunteerApplyStatusChangeService.approve(apply.getId(), centerId);
140+
141+
// then
142+
verify(serverEventPublisher, never()).publish(any());
143+
VolunteerApply approvedApply = volunteerApplyRepository.findById(apply.getId()).orElseThrow();
144+
assertThat(approvedApply.getStatus()).isEqualTo(APPROVED);
145+
}
146+
147+
@DisplayName("지원 상태가 변경된 경우 이벤트 퍼블리셔가 호출된다.")
148+
@Test
149+
void approveWithDifferentStatusPublishesEvent() {
150+
// given
151+
UUID centerId = UUID.randomUUID();
152+
153+
RecruitBoard board = createRecruitBoard(centerId);
154+
recruitBoardRepository.save(board);
155+
156+
VolunteerApply apply = createApply(board.getId());
157+
volunteerApplyRepository.save(apply);
158+
159+
// when
160+
volunteerApplyStatusChangeService.approve(apply.getId(), centerId);
161+
162+
// then
163+
ArgumentCaptor<VolunteerApplyStatusChangeEvent> eventCaptor = ArgumentCaptor.forClass(VolunteerApplyStatusChangeEvent.class);
164+
verify(serverEventPublisher, times(1)).publish(eventCaptor.capture());
165+
166+
VolunteerApplyStatusChangeEvent capturedEvent = eventCaptor.getValue();
167+
assertThat(capturedEvent).isNotNull();
168+
assertThat(capturedEvent.getVolunteerApplyId()).isEqualTo(apply.getId());
169+
}
170+
99171
private VolunteerApply createApply(Long recruitBoardId) {
100172
return VolunteerApply.builder()
101173
.volunteerId(UUID.randomUUID())
@@ -104,5 +176,4 @@ private VolunteerApply createApply(Long recruitBoardId) {
104176
.attended(false)
105177
.build();
106178
}
107-
108179
}

0 commit comments

Comments
 (0)