From b941d08da72d987c8ea5bf8c7696d9c4030245bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:43:53 +0900 Subject: [PATCH 01/54] =?UTF-8?q?refactor(Volunteer):=20Find=20UseCase/Ser?= =?UTF-8?q?vice=EB=A5=BC=20Query=20UseCase/Service=20=EB=A1=9C=20=ED=86=B5?= =?UTF-8?q?=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../usecase/FindVolunteerIdUseCase.java | 8 -- .../usecase/VolunteerQueryUseCase.java | 18 +++++ .../service/FindVolunteerIdServiceTest.java | 77 ------------------- 3 files changed, 18 insertions(+), 85 deletions(-) delete mode 100644 src/main/java/com/somemore/volunteer/usecase/FindVolunteerIdUseCase.java create mode 100644 src/main/java/com/somemore/volunteer/usecase/VolunteerQueryUseCase.java delete mode 100644 src/test/java/com/somemore/volunteer/service/FindVolunteerIdServiceTest.java diff --git a/src/main/java/com/somemore/volunteer/usecase/FindVolunteerIdUseCase.java b/src/main/java/com/somemore/volunteer/usecase/FindVolunteerIdUseCase.java deleted file mode 100644 index 47050b561..000000000 --- a/src/main/java/com/somemore/volunteer/usecase/FindVolunteerIdUseCase.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.somemore.volunteer.usecase; - -import java.util.UUID; - -public interface FindVolunteerIdUseCase { - UUID findVolunteerIdByOAuthId(String oAuthId); - String getNicknameById(UUID id); -} diff --git a/src/main/java/com/somemore/volunteer/usecase/VolunteerQueryUseCase.java b/src/main/java/com/somemore/volunteer/usecase/VolunteerQueryUseCase.java new file mode 100644 index 000000000..e41b69be6 --- /dev/null +++ b/src/main/java/com/somemore/volunteer/usecase/VolunteerQueryUseCase.java @@ -0,0 +1,18 @@ +package com.somemore.volunteer.usecase; + +import com.somemore.volunteer.dto.response.VolunteerResponseDto; + +import java.util.UUID; + +public interface VolunteerQueryUseCase { + + VolunteerResponseDto getMyProfile(UUID volunteerId); + + VolunteerResponseDto getVolunteerProfile(UUID volunteerId); + + VolunteerResponseDto getVolunteerDetailedProfile(UUID volunteerId, UUID centerId); + + UUID getVolunteerIdByOAuthId(String oAuthId); + + String getNicknameById(UUID id); +} diff --git a/src/test/java/com/somemore/volunteer/service/FindVolunteerIdServiceTest.java b/src/test/java/com/somemore/volunteer/service/FindVolunteerIdServiceTest.java deleted file mode 100644 index 831348722..000000000 --- a/src/test/java/com/somemore/volunteer/service/FindVolunteerIdServiceTest.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.somemore.volunteer.service; - -import com.somemore.IntegrationTestSupport; -import com.somemore.auth.oauth.OAuthProvider; -import com.somemore.volunteer.domain.Volunteer; -import com.somemore.volunteer.repository.VolunteerRepository; -import jakarta.persistence.EntityNotFoundException; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; - -import java.util.UUID; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -class FindVolunteerIdServiceTest extends IntegrationTestSupport { - - @Autowired - private FindVolunteerIdService findVolunteerIdService; - - @Autowired - private VolunteerRepository volunteerRepository; - - @AfterEach - void tearDown() { - volunteerRepository.deleteAllInBatch(); - } - - @DisplayName("존재하는 OAuth ID로 봉사자 ID를 조회한다") - @Test - void findVolunteerId() { - // given - String oAuthId = "example-oauth-id"; - Volunteer volunteer = Volunteer.createDefault(OAuthProvider.NAVER, oAuthId); - - volunteerRepository.save(volunteer); - - // when - UUID actualId = findVolunteerIdService.findVolunteerIdByOAuthId(oAuthId); - - // then - assertThat(actualId) - .isNotNull() - .isEqualTo(volunteer.getId()); - } - - @DisplayName("존재하지 않는 OAuth ID로 조회 시 예외를 던진다") - @Test - void throwExceptionWhenVolunteerNotFound() { - // given - String oAuthId = "non-existing-oauth-id"; - - // when - // then - assertThatThrownBy(() -> findVolunteerIdService.findVolunteerIdByOAuthId(oAuthId)) - .isInstanceOf(EntityNotFoundException.class); - } - - @DisplayName("봉사자의 id로 nickname을 조회한다.") - @Test - void getNicknameById() { - - //given - String oAuthId = "example-oauth-id"; - Volunteer volunteer = Volunteer.createDefault(OAuthProvider.NAVER, oAuthId); - - volunteerRepository.save(volunteer); - - //when - String nickname = findVolunteerIdService.getNicknameById(volunteer.getId()); - - //then - assertThat(nickname).isEqualTo(volunteer.getNickname()); - } -} From 9fa8b39d4f10a6596711af8558f5fa1258bce9e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:45:11 +0900 Subject: [PATCH 02/54] =?UTF-8?q?feat(BadRequestException):=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=ED=83=80=EC=9E=85=EC=9D=84=20ExceptionMes?= =?UTF-8?q?sage=EB=8F=84=20=EA=B0=80=EB=8A=A5=ED=95=98=EA=B2=8C=20?= =?UTF-8?q?=EC=98=A4=EB=B2=84=EB=A1=9C=EB=94=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../somemore/domains/VolunteerManagement.java | 25 ------------------- .../global/exception/BadRequestException.java | 4 +++ 2 files changed, 4 insertions(+), 25 deletions(-) delete mode 100644 src/main/java/com/somemore/domains/VolunteerManagement.java diff --git a/src/main/java/com/somemore/domains/VolunteerManagement.java b/src/main/java/com/somemore/domains/VolunteerManagement.java deleted file mode 100644 index 0b0085bd4..000000000 --- a/src/main/java/com/somemore/domains/VolunteerManagement.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.somemore.domains; - -import jakarta.persistence.*; -import lombok.Getter; -import lombok.Setter; -import org.hibernate.annotations.ColumnDefault; - -import java.util.UUID; - -@Getter -@Setter -@Entity -@Table(name = "Volunteer_management") -public class VolunteerManagement { - @Id - @GeneratedValue(strategy = GenerationType.UUID) - private UUID id; - @Column(name = "apply_status", nullable = false, length = 20) - private String applyStatus; - - @ColumnDefault("0") - @Column(name = "attended", nullable = false) - private Boolean attended = false; - -} \ No newline at end of file diff --git a/src/main/java/com/somemore/global/exception/BadRequestException.java b/src/main/java/com/somemore/global/exception/BadRequestException.java index 488546df3..1f0d08221 100644 --- a/src/main/java/com/somemore/global/exception/BadRequestException.java +++ b/src/main/java/com/somemore/global/exception/BadRequestException.java @@ -7,4 +7,8 @@ public class BadRequestException extends RuntimeException{ public BadRequestException(final String message) { super(message); } + + public BadRequestException(final ExceptionMessage message) { + super(message.getMessage()); + } } From 72a0f3ef54563533bf8f04cabbf1352709aa7e4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:47:32 +0900 Subject: [PATCH 03/54] =?UTF-8?q?refactor:=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?UTF-8?q?=20=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../success/CustomOAuthSuccessHandler.java | 6 ++-- .../service/FindVolunteerIdService.java | 32 ------------------- 2 files changed, 3 insertions(+), 35 deletions(-) delete mode 100644 src/main/java/com/somemore/volunteer/service/FindVolunteerIdService.java diff --git a/src/main/java/com/somemore/auth/oauth/handler/success/CustomOAuthSuccessHandler.java b/src/main/java/com/somemore/auth/oauth/handler/success/CustomOAuthSuccessHandler.java index b090b8db4..01d478ac6 100644 --- a/src/main/java/com/somemore/auth/oauth/handler/success/CustomOAuthSuccessHandler.java +++ b/src/main/java/com/somemore/auth/oauth/handler/success/CustomOAuthSuccessHandler.java @@ -6,7 +6,7 @@ import com.somemore.auth.oauth.OAuthProvider; import com.somemore.auth.oauth.naver.service.query.ProcessNaverOAuthUserService; import com.somemore.auth.redirect.RedirectUseCase; -import com.somemore.volunteer.usecase.FindVolunteerIdUseCase; +import com.somemore.volunteer.usecase.VolunteerQueryUseCase; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; @@ -26,7 +26,7 @@ public class CustomOAuthSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { private final ProcessNaverOAuthUserService processNaverOAuthService; - private final FindVolunteerIdUseCase findVolunteerIdUseCase; + private final VolunteerQueryUseCase volunteerQueryUseCase; private final GenerateTokensOnLoginUseCase generateTokensOnLoginUseCase; private final CookieUseCase cookieUseCase; private final RedirectUseCase redirectUseCase; @@ -45,7 +45,7 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo } } - UUID volunteerId = findVolunteerIdUseCase.findVolunteerIdByOAuthId(oAuthId); + UUID volunteerId = volunteerQueryUseCase.getVolunteerIdByOAuthId(oAuthId); EncodedToken accessToken = generateTokensOnLoginUseCase.saveRefreshTokenAndReturnAccessToken(volunteerId); cookieUseCase.setAccessToken(response, accessToken.value()); diff --git a/src/main/java/com/somemore/volunteer/service/FindVolunteerIdService.java b/src/main/java/com/somemore/volunteer/service/FindVolunteerIdService.java deleted file mode 100644 index eab4b0d2b..000000000 --- a/src/main/java/com/somemore/volunteer/service/FindVolunteerIdService.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.somemore.volunteer.service; - -import com.somemore.volunteer.repository.VolunteerRepository; -import com.somemore.volunteer.usecase.FindVolunteerIdUseCase; -import jakarta.persistence.EntityNotFoundException; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import java.util.UUID; - -@Slf4j -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class FindVolunteerIdService implements FindVolunteerIdUseCase { - - private final VolunteerRepository volunteerRepository; - - @Override - public UUID findVolunteerIdByOAuthId(String oAuthId) { - return volunteerRepository.findByOauthId(oAuthId) - .orElseThrow(EntityNotFoundException::new) - .getId(); - } - - @Override - public String getNicknameById(UUID id) { - return volunteerRepository.findNicknameById(id); - } -} From 05cb0ff63523b1bfa93873e91bda733997c00033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:51:13 +0900 Subject: [PATCH 04/54] =?UTF-8?q?feat(VolunteerDetail):=20=EB=A0=88?= =?UTF-8?q?=ED=8F=AC=EC=A7=80=ED=86=A0=EB=A6=AC=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4,=20=EA=B5=AC=ED=98=84=EC=B2=B4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80,=20=EB=A6=AC=ED=94=BD=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VolunteerDetailJpaRepository.java | 7 ++ .../repository/VolunteerDetailRepository.java | 7 +- .../VolunteerDetailRepositoryImpl.java | 68 +++++++++++++++++++ .../service/RegisterVolunteerService.java | 1 + 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/somemore/volunteer/repository/VolunteerDetailJpaRepository.java create mode 100644 src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImpl.java diff --git a/src/main/java/com/somemore/volunteer/repository/VolunteerDetailJpaRepository.java b/src/main/java/com/somemore/volunteer/repository/VolunteerDetailJpaRepository.java new file mode 100644 index 000000000..9c333f15c --- /dev/null +++ b/src/main/java/com/somemore/volunteer/repository/VolunteerDetailJpaRepository.java @@ -0,0 +1,7 @@ +package com.somemore.volunteer.repository; + +import com.somemore.volunteer.domain.VolunteerDetail; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface VolunteerDetailJpaRepository extends JpaRepository { +} diff --git a/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepository.java b/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepository.java index 82e8f96f7..26f43d7ef 100644 --- a/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepository.java +++ b/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepository.java @@ -1,11 +1,14 @@ package com.somemore.volunteer.repository; import com.somemore.volunteer.domain.VolunteerDetail; -import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; import java.util.Optional; import java.util.UUID; -public interface VolunteerDetailRepository extends JpaRepository { +@Repository +public interface VolunteerDetailRepository { + VolunteerDetail save(VolunteerDetail volunteerDetail); Optional findByVolunteerId(UUID volunteerId); + void deleteAllInBatch(); } diff --git a/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImpl.java b/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImpl.java new file mode 100644 index 000000000..794281a38 --- /dev/null +++ b/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImpl.java @@ -0,0 +1,68 @@ +package com.somemore.volunteer.repository; + +import com.querydsl.core.types.Path; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.somemore.volunteer.domain.QVolunteerDetail; +import com.somemore.volunteer.domain.VolunteerDetail; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; + +import java.util.Optional; +import java.util.UUID; + +@RequiredArgsConstructor +@Repository +public class VolunteerDetailRepositoryImpl implements VolunteerDetailRepository { + + private final VolunteerDetailJpaRepository volunteerDetailJpaRepository; + private final JPAQueryFactory queryFactory; + + private final QVolunteerDetail volunteerDetail = QVolunteerDetail.volunteerDetail; + + @Override + public VolunteerDetail save(VolunteerDetail volunteerDetail) { + return volunteerDetailJpaRepository.save(volunteerDetail); + } + + @Override + public Optional findByVolunteerId(UUID volunteerId) { + return findOne(volunteerDetail.volunteerId.eq(volunteerId)); + } + + @Override + public void deleteAllInBatch() { + volunteerDetailJpaRepository.deleteAllInBatch(); + } + + + private Optional findOne(BooleanExpression condition) { + VolunteerDetail result = queryFactory + .selectFrom(volunteerDetail) + .where( + condition, + isNotDeleted() + ) + .fetchOne(); + + return Optional.ofNullable(result); + } + + private Optional findDynamicField(Long id, Path field) { + + return Optional.ofNullable( + queryFactory + .select(field) + .from(volunteerDetail) + .where( + volunteerDetail.id.eq(id), + isNotDeleted() + ) + .fetchOne() + ); + } + + private BooleanExpression isNotDeleted() { + return volunteerDetail.deleted.isFalse(); + } +} diff --git a/src/main/java/com/somemore/volunteer/service/RegisterVolunteerService.java b/src/main/java/com/somemore/volunteer/service/RegisterVolunteerService.java index 8feb930c1..e27a8c077 100644 --- a/src/main/java/com/somemore/volunteer/service/RegisterVolunteerService.java +++ b/src/main/java/com/somemore/volunteer/service/RegisterVolunteerService.java @@ -3,6 +3,7 @@ import com.somemore.volunteer.domain.Volunteer; import com.somemore.volunteer.domain.VolunteerDetail; import com.somemore.volunteer.dto.request.VolunteerRegisterRequestDto; +import com.somemore.volunteer.repository.VolunteerDetailJpaRepository; import com.somemore.volunteer.repository.VolunteerDetailRepository; import com.somemore.volunteer.repository.VolunteerRepository; import com.somemore.volunteer.usecase.RegisterVolunteerUseCase; From df033e26c54293f14ca1fc1e396ba2f0e568461d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:53:49 +0900 Subject: [PATCH 05/54] =?UTF-8?q?feat(Volunteer):=20Volunteer=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/VolunteerQueryService.java | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java diff --git a/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java b/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java new file mode 100644 index 000000000..12fe4a64e --- /dev/null +++ b/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java @@ -0,0 +1,78 @@ +package com.somemore.volunteer.service; + +import com.somemore.global.exception.BadRequestException; +import com.somemore.volunteer.domain.Volunteer; +import com.somemore.volunteer.domain.VolunteerDetail; +import com.somemore.volunteer.dto.response.VolunteerResponseDto; +import com.somemore.volunteer.repository.VolunteerDetailRepository; +import com.somemore.volunteer.repository.VolunteerRepository; +import com.somemore.volunteer.usecase.VolunteerQueryUseCase; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.UUID; + +import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_VOLUNTEER; + +@Slf4j +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class VolunteerQueryService implements VolunteerQueryUseCase { + + private final VolunteerRepository volunteerRepository; + private final VolunteerDetailRepository volunteerDetailRepository; + + @Override + public VolunteerResponseDto getMyProfile(UUID volunteerId) { + + return VolunteerResponseDto.from( + findVolunteer(volunteerId), + findVolunteerDetail(volunteerId) + ); + } + + @Override + public VolunteerResponseDto getVolunteerProfile(UUID volunteerId) { + + return VolunteerResponseDto.from( + findVolunteer(volunteerId) + ); + } + + @Override + public VolunteerResponseDto getVolunteerDetailedProfile(UUID volunteerId, UUID centerId) { + // TODO 권한 검사 + + + return VolunteerResponseDto.from( + findVolunteer(volunteerId), + findVolunteerDetail(volunteerId) + ); + } + + @Override + public UUID getVolunteerIdByOAuthId(String oAuthId) { + return volunteerRepository.findByOauthId(oAuthId) + .orElseThrow(() -> new BadRequestException(NOT_EXISTS_VOLUNTEER)) + .getId(); + } + + @Override + public String getNicknameById(UUID id) { + return volunteerRepository.findNicknameById(id); + } + + private Volunteer findVolunteer(UUID volunteerId) { + return volunteerRepository.findById(volunteerId) + .orElseThrow(() -> new BadRequestException(NOT_EXISTS_VOLUNTEER)); + + } + + private VolunteerDetail findVolunteerDetail(UUID volunteerId) { + return volunteerDetailRepository.findByVolunteerId(volunteerId) + .orElseThrow(() -> new BadRequestException(NOT_EXISTS_VOLUNTEER)); + } +} From b3bfdbbc91030b4b8c64bfcdd54aa06cedd1a287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:54:56 +0900 Subject: [PATCH 06/54] =?UTF-8?q?feat(Volunteer):=20=EB=A0=88=ED=8F=AC?= =?UTF-8?q?=EC=A7=80=ED=86=A0=EB=A6=AC=20=EC=9D=B8=ED=84=B0=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4,=20=EA=B5=AC=ED=98=84=EC=B2=B4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80,=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/VolunteerJpaRepository.java | 2 +- .../repository/VolunteerRepository.java | 3 +- .../repository/VolunteerRepositoryImpl.java | 58 +++++++++++++++---- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/somemore/volunteer/repository/VolunteerJpaRepository.java b/src/main/java/com/somemore/volunteer/repository/VolunteerJpaRepository.java index f7261b45d..362a63daa 100644 --- a/src/main/java/com/somemore/volunteer/repository/VolunteerJpaRepository.java +++ b/src/main/java/com/somemore/volunteer/repository/VolunteerJpaRepository.java @@ -4,7 +4,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import java.util.Optional; +import java.util.UUID; public interface VolunteerJpaRepository extends JpaRepository { - Optional findByOauthId(String oauthId); } diff --git a/src/main/java/com/somemore/volunteer/repository/VolunteerRepository.java b/src/main/java/com/somemore/volunteer/repository/VolunteerRepository.java index 03c29cad3..364db842b 100644 --- a/src/main/java/com/somemore/volunteer/repository/VolunteerRepository.java +++ b/src/main/java/com/somemore/volunteer/repository/VolunteerRepository.java @@ -9,7 +9,8 @@ @Repository public interface VolunteerRepository { Volunteer save(Volunteer volunteer); - String findNicknameById(UUID id); + Optional findById(UUID id); Optional findByOauthId(String oauthId); + String findNicknameById(UUID id); void deleteAllInBatch(); } diff --git a/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java b/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java index b47f5afbc..87a6ef8f6 100644 --- a/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java +++ b/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java @@ -1,5 +1,7 @@ package com.somemore.volunteer.repository; +import com.querydsl.core.types.Path; +import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import com.somemore.volunteer.domain.QVolunteer; import com.somemore.volunteer.domain.Volunteer; @@ -8,37 +10,71 @@ import java.util.Optional; import java.util.UUID; +import java.util.function.Function; @RequiredArgsConstructor @Repository -public class VolunteerRepositoryImpl implements VolunteerRepository{ +public class VolunteerRepositoryImpl implements VolunteerRepository { private final VolunteerJpaRepository volunteerJpaRepository; private final JPAQueryFactory queryFactory; + private final QVolunteer volunteer = QVolunteer.volunteer; + @Override public Volunteer save(Volunteer volunteer) { return volunteerJpaRepository.save(volunteer); } @Override - public String findNicknameById(UUID id) { - QVolunteer volunteer = QVolunteer.volunteer; - - return queryFactory - .select(volunteer.nickname) - .from(volunteer) - .where(volunteer.id.eq(id)) - .fetchOne(); + public Optional findById(UUID id) { + return findOne(volunteer.id.eq(id)); } @Override public Optional findByOauthId(String oauthId) { - return volunteerJpaRepository.findByOauthId(oauthId); + return findOne(volunteer.oauthId.eq(oauthId)); + } + + @Override + public String findNicknameById(UUID id) { + return findDynamicField(id, volunteer.nickname) + .orElse(null); } @Override public void deleteAllInBatch() { volunteerJpaRepository.deleteAllInBatch(); } -} + + private Optional findOne(BooleanExpression condition) { + + return Optional.ofNullable( + queryFactory + .selectFrom(volunteer) + .where( + condition, + isNotDeleted() + ) + .fetchOne() + ); + } + + private Optional findDynamicField(UUID id, Path field) { + + return Optional.ofNullable( + queryFactory + .select(field) + .from(volunteer) + .where( + volunteer.id.eq(id), + isNotDeleted() + ) + .fetchOne() + ); + } + + private BooleanExpression isNotDeleted() { + return volunteer.deleted.isFalse(); + } +} \ No newline at end of file From 72b2cfa56cf1053c31a5367e40c5390211410357 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:56:42 +0900 Subject: [PATCH 07/54] =?UTF-8?q?feat(Volunteer):=20=EC=A1=B4=EC=9E=AC?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=EB=B4=89=EC=82=AC?= =?UTF-8?q?=EC=9E=90=20=EC=B2=98=EB=A6=AC=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/somemore/global/exception/ExceptionMessage.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/somemore/global/exception/ExceptionMessage.java b/src/main/java/com/somemore/global/exception/ExceptionMessage.java index 1aa5d8fdd..492a53e16 100644 --- a/src/main/java/com/somemore/global/exception/ExceptionMessage.java +++ b/src/main/java/com/somemore/global/exception/ExceptionMessage.java @@ -8,8 +8,8 @@ @Getter public enum ExceptionMessage { - NOT_EXISTS_CENTER("존재하지 않는 기관 입니다."), - NOT_EXISTS_COMMUNITY_BOARD("존재하지 않는 게시글 입니다."), + NOT_EXISTS_CENTER("존재하지 않는 기관입니다."), + NOT_EXISTS_COMMUNITY_BOARD("존재하지 않는 게시글입니다."), UNAUTHORIZED_COMMUNITY_BOARD("해당 게시글에 권한이 없습니다."), NOT_EXISTS_COMMUNITY_COMMENT("존재하지 않는 댓글 입니다."), UNAUTHORIZED_COMMUNITY_COMMENT("해당 댓글에 권한이 없습니다."), From 7130dbc242c88e9c4ed5d589af36138c9f33124e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:57:08 +0900 Subject: [PATCH 08/54] =?UTF-8?q?feat(VolunteerDetail):=20baseEntity=20?= =?UTF-8?q?=EC=83=81=EC=86=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/somemore/volunteer/domain/VolunteerDetail.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/somemore/volunteer/domain/VolunteerDetail.java b/src/main/java/com/somemore/volunteer/domain/VolunteerDetail.java index 9f9321a29..f1eb33ce6 100644 --- a/src/main/java/com/somemore/volunteer/domain/VolunteerDetail.java +++ b/src/main/java/com/somemore/volunteer/domain/VolunteerDetail.java @@ -1,5 +1,6 @@ package com.somemore.volunteer.domain; +import com.somemore.global.common.BaseEntity; import com.somemore.volunteer.dto.request.VolunteerRegisterRequestDto; import jakarta.persistence.*; import lombok.AccessLevel; @@ -13,7 +14,7 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity @Table(name = "volunteer_detail") -public class VolunteerDetail { +public class VolunteerDetail extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) From 9a0e2f61e92f76bfc2d923115b78396c9689f7de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Thu, 28 Nov 2024 17:01:55 +0900 Subject: [PATCH 09/54] =?UTF-8?q?feat:=20Volunteer=20=EB=B0=8F=20Volunteer?= =?UTF-8?q?Detail=20=EC=97=94=ED=8B=B0=ED=8B=B0=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20DTO=20=EB=B3=80=ED=99=98=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Volunteer, VolunteerDetail 데이터 매핑. - VolunteerDetail 포함/미포함 두 가지 방식 지원. --- .../dto/response/VolunteerResponseDto.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 src/main/java/com/somemore/volunteer/dto/response/VolunteerResponseDto.java diff --git a/src/main/java/com/somemore/volunteer/dto/response/VolunteerResponseDto.java b/src/main/java/com/somemore/volunteer/dto/response/VolunteerResponseDto.java new file mode 100644 index 000000000..37725f14c --- /dev/null +++ b/src/main/java/com/somemore/volunteer/dto/response/VolunteerResponseDto.java @@ -0,0 +1,71 @@ +package com.somemore.volunteer.dto.response; + +import com.somemore.volunteer.domain.Volunteer; +import com.somemore.volunteer.domain.VolunteerDetail; + +public record VolunteerResponseDto( + String volunteerId, + String nickname, + String imgUrl, + String introduce, + String tier, + Integer totalVolunteerHours, + Integer totalVolunteerCount, + VolunteerDetailResponseDto volunteerDetailResponseDto +) { + + public static VolunteerResponseDto from( + Volunteer volunteer, + VolunteerDetail volunteerDetail + ) { + return new VolunteerResponseDto( + volunteer.getId().toString(), + volunteer.getNickname(), + volunteer.getImgUrl(), + volunteer.getIntroduce(), + volunteer.getTier().name(), + volunteer.getTotalVolunteerHours(), + volunteer.getTotalVolunteerCount(), + VolunteerDetailResponseDto.from(volunteerDetail) + ); + } + + public static VolunteerResponseDto from( + Volunteer volunteer + ) { + return new VolunteerResponseDto( + volunteer.getId().toString(), + volunteer.getNickname(), + volunteer.getImgUrl(), + volunteer.getIntroduce(), + volunteer.getTier().name(), + volunteer.getTotalVolunteerHours(), + volunteer.getTotalVolunteerCount(), + null + ); + } + + private record VolunteerDetailResponseDto( + String name, + String email, + String gender, + String birthDate, + String contactNumber + ) { + public static VolunteerDetailResponseDto from( + VolunteerDetail volunteerDetail + ) { + return new VolunteerDetailResponseDto( + volunteerDetail.getName(), + volunteerDetail.getEmail(), + volunteerDetail.getGender().name(), + volunteerDetail.getBirthDate(), + volunteerDetail.getContactNumber() + ); + } + } + + +} + + From c737e850d57d125eb873b2e5c0054a76aedadd04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Thu, 28 Nov 2024 17:02:32 +0900 Subject: [PATCH 10/54] =?UTF-8?q?refactor:=20=EA=B8=B0=EC=A1=B4=EC=9D=98?= =?UTF-8?q?=20findService=EB=A5=BC=20QueryService=EB=A1=9C=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/VolunteerQueryServiceTest.java | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/test/java/com/somemore/volunteer/service/VolunteerQueryServiceTest.java diff --git a/src/test/java/com/somemore/volunteer/service/VolunteerQueryServiceTest.java b/src/test/java/com/somemore/volunteer/service/VolunteerQueryServiceTest.java new file mode 100644 index 000000000..ec8454d77 --- /dev/null +++ b/src/test/java/com/somemore/volunteer/service/VolunteerQueryServiceTest.java @@ -0,0 +1,79 @@ +package com.somemore.volunteer.service; + +import com.somemore.IntegrationTestSupport; +import com.somemore.auth.oauth.OAuthProvider; +import com.somemore.global.exception.BadRequestException; +import com.somemore.volunteer.domain.Volunteer; +import com.somemore.volunteer.repository.VolunteerRepository; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.UUID; + +import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_VOLUNTEER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class VolunteerQueryServiceTest extends IntegrationTestSupport { + + @Autowired + private VolunteerQueryService volunteerQueryService; + + @Autowired + private VolunteerRepository volunteerRepository; + + @AfterEach + void tearDown() { + volunteerRepository.deleteAllInBatch(); + } + + @DisplayName("존재하는 OAuth ID로 봉사자 ID를 조회한다") + @Test + void findVolunteerId() { + // given + String oAuthId = "example-oauth-id"; + Volunteer volunteer = Volunteer.createDefault(OAuthProvider.NAVER, oAuthId); + + volunteerRepository.save(volunteer); + + // when + UUID actualId = volunteerQueryService.getVolunteerIdByOAuthId(oAuthId); + + // then + assertThat(actualId) + .isNotNull() + .isEqualTo(volunteer.getId()); + } + + @DisplayName("존재하지 않는 OAuth ID로 조회 시 예외를 던진다") + @Test + void throwExceptionWhenVolunteerNotFound() { + // given + String oAuthId = "non-existing-oauth-id"; + + // when + // then + assertThatThrownBy(() -> volunteerQueryService.getVolunteerIdByOAuthId(oAuthId)) + .isInstanceOf(BadRequestException.class) + .hasMessage(NOT_EXISTS_VOLUNTEER.getMessage()); + } + + @DisplayName("봉사자의 id로 nickname을 조회한다.") + @Test + void getNicknameById() { + + //given + String oAuthId = "example-oauth-id"; + Volunteer volunteer = Volunteer.createDefault(OAuthProvider.NAVER, oAuthId); + + volunteerRepository.save(volunteer); + + //when + String nickname = volunteerQueryService.getNicknameById(volunteer.getId()); + + //then + assertThat(nickname).isEqualTo(volunteer.getNickname()); + } +} From 793e279ce9f0d68102ae59d644c6d69c379d1381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Thu, 28 Nov 2024 17:16:08 +0900 Subject: [PATCH 11/54] =?UTF-8?q?feat(VolunteerQueryController):=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/VolunteerQueryController.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 src/main/java/com/somemore/volunteer/controller/VolunteerQueryController.java diff --git a/src/main/java/com/somemore/volunteer/controller/VolunteerQueryController.java b/src/main/java/com/somemore/volunteer/controller/VolunteerQueryController.java new file mode 100644 index 000000000..47787d9c9 --- /dev/null +++ b/src/main/java/com/somemore/volunteer/controller/VolunteerQueryController.java @@ -0,0 +1,60 @@ +package com.somemore.volunteer.controller; + +import com.somemore.global.common.response.ApiResponse; +import com.somemore.volunteer.dto.response.VolunteerResponseDto; +import com.somemore.volunteer.usecase.VolunteerQueryUseCase; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +import java.util.UUID; + +@RestController +@Slf4j +@RequiredArgsConstructor +@Tag(name = "Find Volunteer", description = "Find Volunteer") +public class VolunteerQueryController { + + private final VolunteerQueryUseCase volunteerQueryUseCase; + + @GetMapping("/profile/me") + @Operation(summary = "본인 상세 프로필 조회", description = "현재 로그인된 사용자의 상세 프로필을 조회합니다.") + public ApiResponse getMyProfile( + @AuthenticationPrincipal String volunteerId) { + + return ApiResponse.ok( + 200, + volunteerQueryUseCase.getMyProfile(UUID.fromString(volunteerId)), + "프로필 조회 성공"); + } + + @GetMapping("/profile/{volunteerId}") + @Operation(summary = "타인 프로필 조회", description = "특정 봉사자의 프로필을 조회합니다. 상세 정보는 포함되지 않습니다.") + public ApiResponse getVolunteerProfile( + @PathVariable UUID volunteerId) { + + return ApiResponse.ok( + 200, + volunteerQueryUseCase.getVolunteerProfile(volunteerId), + "프로필 조회 성공" + ); + } + + @GetMapping("/profile/{volunteerId}/detailed") + @Operation(summary = "타인 상세 프로필 조회", description = "기관이 작성한 모집 글에 지원한 봉사자의 상세 프로필을 조회합니다.") + public ApiResponse getVolunteerDetailedProfile( + @PathVariable UUID volunteerId, + @AuthenticationPrincipal String centerId) { + + return ApiResponse.ok( + 200, + volunteerQueryUseCase.getVolunteerDetailedProfile(volunteerId, UUID.fromString(centerId)), + "프로필 조회 성공" + ); + } +} From 2c89fe061f1cdf7e7959fb231ad2dcada830d320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 21:33:52 +0900 Subject: [PATCH 12/54] =?UTF-8?q?feat(VolunteerApply):=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=EC=99=80=20ApplyStatus=20ENUM=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../volunteerApply/domain/ApplyStatus.java | 7 +++ .../volunteerApply/domain/VolunteerApply.java | 44 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/main/java/com/somemore/volunteerApply/domain/ApplyStatus.java create mode 100644 src/main/java/com/somemore/volunteerApply/domain/VolunteerApply.java diff --git a/src/main/java/com/somemore/volunteerApply/domain/ApplyStatus.java b/src/main/java/com/somemore/volunteerApply/domain/ApplyStatus.java new file mode 100644 index 000000000..eddb7b073 --- /dev/null +++ b/src/main/java/com/somemore/volunteerApply/domain/ApplyStatus.java @@ -0,0 +1,7 @@ +package com.somemore.volunteerApply.domain; + +public enum ApplyStatus { + WAITING, + APPROVED, + REJECTED +} diff --git a/src/main/java/com/somemore/volunteerApply/domain/VolunteerApply.java b/src/main/java/com/somemore/volunteerApply/domain/VolunteerApply.java new file mode 100644 index 000000000..da51dff6d --- /dev/null +++ b/src/main/java/com/somemore/volunteerApply/domain/VolunteerApply.java @@ -0,0 +1,44 @@ +package com.somemore.volunteerApply.domain; + +import com.somemore.global.common.BaseEntity; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.util.UUID; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +@Table(name = "volunteer_apply") +public class VolunteerApply extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "volunteer_id", nullable = false, columnDefinition = "BINARY(16)") + private UUID volunteerId; + + @Column(name = "recruit_board_id", nullable = false) + private Long recruitBoardId; + + @Enumerated(EnumType.STRING) + @Column(name = "status", nullable = false, length = 20) + private ApplyStatus status; + + @Column(name = "attended", nullable = false) + private Boolean attended; + + @Builder + public VolunteerApply(UUID volunteerId, Long recruitBoardId, ApplyStatus status, Boolean attended) { + this.volunteerId = volunteerId; + this.recruitBoardId = recruitBoardId; + this.status = status != null ? status : ApplyStatus.WAITING; + this.attended = attended != null ? attended : false; + } +} + +// TODO 상태 업데이트 메서드들을 만들고 빌더에서 status를 변경 불가하도록 \ No newline at end of file From 9510c4bdbb515bd21d4de2e6580795c4200e5fd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 21:37:44 +0900 Subject: [PATCH 13/54] =?UTF-8?q?feat(VolunteerDetailRepository):=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/exception/ExceptionMessage.java | 4 +++- .../repository/VolunteerDetailRepository.java | 1 - .../VolunteerDetailRepositoryImpl.java | 21 ------------------- 3 files changed, 3 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/somemore/global/exception/ExceptionMessage.java b/src/main/java/com/somemore/global/exception/ExceptionMessage.java index 492a53e16..257147885 100644 --- a/src/main/java/com/somemore/global/exception/ExceptionMessage.java +++ b/src/main/java/com/somemore/global/exception/ExceptionMessage.java @@ -14,13 +14,15 @@ public enum ExceptionMessage { NOT_EXISTS_COMMUNITY_COMMENT("존재하지 않는 댓글 입니다."), UNAUTHORIZED_COMMUNITY_COMMENT("해당 댓글에 권한이 없습니다."), NOT_EXISTS_LOCATION("존재하지 않는 위치 ID 입니다."), - NOT_EXISTS_RECRUIT_BOARD("존재하지 않는 봉사 모집글 ID 입니다."), + NOT_EXISTS_RECRUIT_BOARD("존재하지 않는 봉사 모집글입니다."), UNAUTHORIZED_RECRUIT_BOARD("해당 봉사 모집글에 권한이 없습니다."), UPLOAD_FAILED("파일 업로드에 실패했습니다."), INVALID_FILE_TYPE("지원하지 않는 파일 형식입니다."), FILE_SIZE_EXCEEDED("파일 크기가 허용된 한도를 초과했습니다."), EMPTY_FILE("파일이 존재하지 않습니다."), INSTANTIATION_NOT_ALLOWED("인스턴스화 할 수 없는 클래스 입니다."), + NOT_EXISTS_VOLUNTEER("존재하지 않는 봉사자입니다."), + UNAUTHORIZED_VOLUNTEER_DETAIL("해당 봉사자의 상세 정보 조회 권한이 없습니다."), CANNOT_CANCEL_DELETED_INTEREST_CENTER("이미 삭제된 관심 기관은 취소할 수 없습니다."), DUPLICATE_INTEREST_CENTER("이미 관심 표시한 기관입니다.") ; diff --git a/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepository.java b/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepository.java index 26f43d7ef..2ce9cb40a 100644 --- a/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepository.java +++ b/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepository.java @@ -10,5 +10,4 @@ public interface VolunteerDetailRepository { VolunteerDetail save(VolunteerDetail volunteerDetail); Optional findByVolunteerId(UUID volunteerId); - void deleteAllInBatch(); } diff --git a/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImpl.java b/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImpl.java index 794281a38..2bdf71c2e 100644 --- a/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImpl.java +++ b/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImpl.java @@ -1,6 +1,5 @@ package com.somemore.volunteer.repository; -import com.querydsl.core.types.Path; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; import com.somemore.volunteer.domain.QVolunteerDetail; @@ -30,12 +29,6 @@ public Optional findByVolunteerId(UUID volunteerId) { return findOne(volunteerDetail.volunteerId.eq(volunteerId)); } - @Override - public void deleteAllInBatch() { - volunteerDetailJpaRepository.deleteAllInBatch(); - } - - private Optional findOne(BooleanExpression condition) { VolunteerDetail result = queryFactory .selectFrom(volunteerDetail) @@ -48,20 +41,6 @@ private Optional findOne(BooleanExpression condition) { return Optional.ofNullable(result); } - private Optional findDynamicField(Long id, Path field) { - - return Optional.ofNullable( - queryFactory - .select(field) - .from(volunteerDetail) - .where( - volunteerDetail.id.eq(id), - isNotDeleted() - ) - .fetchOne() - ); - } - private BooleanExpression isNotDeleted() { return volunteerDetail.deleted.isFalse(); } From 8b9c593e47eb625557e3b687b2d2617b2b1e8265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 21:39:04 +0900 Subject: [PATCH 14/54] =?UTF-8?q?test(VolunteerRepository):=20=EB=B4=89?= =?UTF-8?q?=EC=82=AC=EC=9E=90=20id,=20OAuth=20id=EB=A1=9C=20=EB=B4=89?= =?UTF-8?q?=EC=82=AC=EC=9E=90=20=EC=A0=95=EB=B3=B4=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/VolunteerRepositoryTest.java | 66 ++++++++++++++++--- 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/src/test/java/com/somemore/volunteer/repository/VolunteerRepositoryTest.java b/src/test/java/com/somemore/volunteer/repository/VolunteerRepositoryTest.java index e9d0cf63c..c0f63d749 100644 --- a/src/test/java/com/somemore/volunteer/repository/VolunteerRepositoryTest.java +++ b/src/test/java/com/somemore/volunteer/repository/VolunteerRepositoryTest.java @@ -3,31 +3,77 @@ import com.somemore.IntegrationTestSupport; import com.somemore.auth.oauth.OAuthProvider; import com.somemore.volunteer.domain.Volunteer; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; +import java.util.Optional; +import java.util.UUID; + import static org.assertj.core.api.Assertions.assertThat; @Transactional class VolunteerRepositoryTest extends IntegrationTestSupport { + @Autowired private VolunteerRepository volunteerRepository; - @DisplayName("봉사자의 id로 닉네임을 조회한다. (Repository)") - @Test - void findNicknameById() { - //given - String oAuthId = "example-oauth-id"; - Volunteer volunteer = Volunteer.createDefault(OAuthProvider.NAVER, oAuthId); - + String oAuthId; + Volunteer volunteer; + + @BeforeEach + void setup() { + oAuthId = "example-oauth-id"; + volunteer = Volunteer.createDefault(OAuthProvider.NAVER, oAuthId); volunteerRepository.save(volunteer); + } - //when + @DisplayName("봉사자의 id로 닉네임을 조회한다.") + @Test + void findNicknameById() { + // when String volunteerNickname = volunteerRepository.findNicknameById(volunteer.getId()); - //then + // then assertThat(volunteerNickname).isEqualTo(volunteer.getNickname()); } -} + + @DisplayName("올바르지 않은 봉사자의 id로 닉네임을 조회하면 null을 반환한다.") + @Test + void findNicknameByInvalidId() { + // given + UUID inValidVolunteerId = UUID.randomUUID(); + + // when + String volunteerNickname = volunteerRepository.findNicknameById(inValidVolunteerId); + + // then + assertThat(volunteerNickname).isNull(); + } + + @DisplayName("봉사자의 id로 봉사자 정보를 조회한다.") + @Test + void findById() { + // when + Optional foundVolunteer = volunteerRepository.findById(volunteer.getId()); + + // then + assertThat(foundVolunteer).isPresent(); + assertThat(foundVolunteer.get().getId()).isEqualTo(volunteer.getId()); + assertThat(foundVolunteer.get().getNickname()).isEqualTo(volunteer.getNickname()); + } + + @DisplayName("OAuth ID로 봉사자 정보를 조회한다.") + @Test + void findByOauthId() { + // when + Optional foundVolunteer = volunteerRepository.findByOauthId(oAuthId); + + // then + assertThat(foundVolunteer).isPresent(); + assertThat(foundVolunteer.get().getOauthId()).isEqualTo(oAuthId); + assertThat(foundVolunteer.get().getNickname()).isEqualTo(volunteer.getNickname()); + } +} \ No newline at end of file From 849b0d01d8872d7887f1fcfdb657e1db02396276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 21:51:28 +0900 Subject: [PATCH 15/54] =?UTF-8?q?test(RecruitBoardFixture):=20completed=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=EC=9D=98=20RecruitBoard=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 리플렉션을 이용해서 status를 수정. --- .../common/fixture/RecruitBoardFixture.java | 352 ++++++++++-------- 1 file changed, 195 insertions(+), 157 deletions(-) diff --git a/src/test/java/com/somemore/common/fixture/RecruitBoardFixture.java b/src/test/java/com/somemore/common/fixture/RecruitBoardFixture.java index 1ca16287b..d9af6099e 100644 --- a/src/test/java/com/somemore/common/fixture/RecruitBoardFixture.java +++ b/src/test/java/com/somemore/common/fixture/RecruitBoardFixture.java @@ -1,14 +1,17 @@ package com.somemore.common.fixture; -import static com.somemore.common.fixture.LocalDateTimeFixture.createStartDateTime; -import static com.somemore.recruitboard.domain.VolunteerType.OTHER; - import com.somemore.recruitboard.domain.RecruitBoard; +import com.somemore.recruitboard.domain.RecruitStatus; import com.somemore.recruitboard.domain.RecruitmentInfo; import com.somemore.recruitboard.domain.VolunteerType; + +import java.lang.reflect.Field; import java.time.LocalDateTime; import java.util.UUID; +import static com.somemore.common.fixture.LocalDateTimeFixture.createStartDateTime; +import static com.somemore.recruitboard.domain.VolunteerType.OTHER; + public class RecruitBoardFixture { public static final String REGION = "경기"; @@ -28,231 +31,266 @@ private RecruitBoardFixture() { public static RecruitBoard createRecruitBoard() { RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() - .region(REGION) - .recruitmentCount(RECRUITMENT_COUNT) - .volunteerStartDateTime(START_DATE_TIME) - .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) - .admitted(ADMITTED) - .build(); + .region(REGION) + .recruitmentCount(RECRUITMENT_COUNT) + .volunteerStartDateTime(START_DATE_TIME) + .volunteerEndDateTime(END_DATE_TIME) + .volunteerType(VOLUNTEER_TYPE) + .admitted(ADMITTED) + .build(); return RecruitBoard.builder() - .centerId(UUID.randomUUID()) - .locationId(LOCATION_ID) - .title(TITLE) - .content(CONTENT) - .imgUrl(IMG_URL) - .recruitmentInfo(recruitmentInfo) - .build(); + .centerId(UUID.randomUUID()) + .locationId(LOCATION_ID) + .title(TITLE) + .content(CONTENT) + .imgUrl(IMG_URL) + .recruitmentInfo(recruitmentInfo) + .build(); } public static RecruitBoard createRecruitBoard(String title) { RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() - .region(REGION) - .recruitmentCount(RECRUITMENT_COUNT) - .volunteerStartDateTime(START_DATE_TIME) - .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) - .admitted(ADMITTED) - .build(); + .region(REGION) + .recruitmentCount(RECRUITMENT_COUNT) + .volunteerStartDateTime(START_DATE_TIME) + .volunteerEndDateTime(END_DATE_TIME) + .volunteerType(VOLUNTEER_TYPE) + .admitted(ADMITTED) + .build(); return RecruitBoard.builder() - .centerId(UUID.randomUUID()) - .locationId(LOCATION_ID) - .title(title) - .content(CONTENT) - .imgUrl(IMG_URL) - .recruitmentInfo(recruitmentInfo) - .build(); + .centerId(UUID.randomUUID()) + .locationId(LOCATION_ID) + .title(title) + .content(CONTENT) + .imgUrl(IMG_URL) + .recruitmentInfo(recruitmentInfo) + .build(); } public static RecruitBoard createRecruitBoard(String title, UUID centerId, Long locationId) { RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() - .region(REGION) - .recruitmentCount(RECRUITMENT_COUNT) - .volunteerStartDateTime(START_DATE_TIME) - .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) - .admitted(ADMITTED) - .build(); + .region(REGION) + .recruitmentCount(RECRUITMENT_COUNT) + .volunteerStartDateTime(START_DATE_TIME) + .volunteerEndDateTime(END_DATE_TIME) + .volunteerType(VOLUNTEER_TYPE) + .admitted(ADMITTED) + .build(); return RecruitBoard.builder() - .centerId(centerId) - .locationId(locationId) - .title(title) - .content(CONTENT) - .imgUrl(IMG_URL) - .recruitmentInfo(recruitmentInfo) - .build(); + .centerId(centerId) + .locationId(locationId) + .title(title) + .content(CONTENT) + .imgUrl(IMG_URL) + .recruitmentInfo(recruitmentInfo) + .build(); } public static RecruitBoard createRecruitBoard(String title, UUID centerId) { RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() - .region(REGION) - .recruitmentCount(RECRUITMENT_COUNT) - .volunteerStartDateTime(START_DATE_TIME) - .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) - .admitted(ADMITTED) - .build(); + .region(REGION) + .recruitmentCount(RECRUITMENT_COUNT) + .volunteerStartDateTime(START_DATE_TIME) + .volunteerEndDateTime(END_DATE_TIME) + .volunteerType(VOLUNTEER_TYPE) + .admitted(ADMITTED) + .build(); return RecruitBoard.builder() - .centerId(centerId) - .locationId(LOCATION_ID) - .title(title) - .content(CONTENT) - .imgUrl(IMG_URL) - .recruitmentInfo(recruitmentInfo) - .build(); + .centerId(centerId) + .locationId(LOCATION_ID) + .title(title) + .content(CONTENT) + .imgUrl(IMG_URL) + .recruitmentInfo(recruitmentInfo) + .build(); } public static RecruitBoard createRecruitBoard(VolunteerType type, UUID centerId) { RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() - .region(REGION) - .recruitmentCount(RECRUITMENT_COUNT) - .volunteerStartDateTime(START_DATE_TIME) - .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(type) - .admitted(ADMITTED) - .build(); + .region(REGION) + .recruitmentCount(RECRUITMENT_COUNT) + .volunteerStartDateTime(START_DATE_TIME) + .volunteerEndDateTime(END_DATE_TIME) + .volunteerType(type) + .admitted(ADMITTED) + .build(); return RecruitBoard.builder() - .centerId(centerId) - .locationId(LOCATION_ID) - .title(TITLE) - .content(CONTENT) - .imgUrl(IMG_URL) - .recruitmentInfo(recruitmentInfo) - .build(); + .centerId(centerId) + .locationId(LOCATION_ID) + .title(TITLE) + .content(CONTENT) + .imgUrl(IMG_URL) + .recruitmentInfo(recruitmentInfo) + .build(); } public static RecruitBoard createRecruitBoard(Boolean admitted, UUID centerId) { RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() - .region(REGION) - .recruitmentCount(RECRUITMENT_COUNT) - .volunteerStartDateTime(START_DATE_TIME) - .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) - .admitted(admitted) - .build(); + .region(REGION) + .recruitmentCount(RECRUITMENT_COUNT) + .volunteerStartDateTime(START_DATE_TIME) + .volunteerEndDateTime(END_DATE_TIME) + .volunteerType(VOLUNTEER_TYPE) + .admitted(admitted) + .build(); return RecruitBoard.builder() - .centerId(centerId) - .locationId(LOCATION_ID) - .title(TITLE) - .content(CONTENT) - .imgUrl(IMG_URL) - .recruitmentInfo(recruitmentInfo) - .build(); + .centerId(centerId) + .locationId(LOCATION_ID) + .title(TITLE) + .content(CONTENT) + .imgUrl(IMG_URL) + .recruitmentInfo(recruitmentInfo) + .build(); } public static RecruitBoard createRecruitBoard(Long locationId) { RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() - .region(REGION) - .recruitmentCount(RECRUITMENT_COUNT) - .volunteerStartDateTime(START_DATE_TIME) - .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) - .admitted(ADMITTED) - .build(); + .region(REGION) + .recruitmentCount(RECRUITMENT_COUNT) + .volunteerStartDateTime(START_DATE_TIME) + .volunteerEndDateTime(END_DATE_TIME) + .volunteerType(VOLUNTEER_TYPE) + .admitted(ADMITTED) + .build(); return RecruitBoard.builder() - .centerId(UUID.randomUUID()) - .locationId(locationId) - .title(TITLE) - .content(CONTENT) - .imgUrl(IMG_URL) - .recruitmentInfo(recruitmentInfo) - .build(); + .centerId(UUID.randomUUID()) + .locationId(locationId) + .title(TITLE) + .content(CONTENT) + .imgUrl(IMG_URL) + .recruitmentInfo(recruitmentInfo) + .build(); } public static RecruitBoard createRecruitBoard(UUID centerId) { RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() - .region(REGION) - .recruitmentCount(RECRUITMENT_COUNT) - .volunteerStartDateTime(START_DATE_TIME) - .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) - .admitted(ADMITTED) - .build(); + .region(REGION) + .recruitmentCount(RECRUITMENT_COUNT) + .volunteerStartDateTime(START_DATE_TIME) + .volunteerEndDateTime(END_DATE_TIME) + .volunteerType(VOLUNTEER_TYPE) + .admitted(ADMITTED) + .build(); return RecruitBoard.builder() - .centerId(centerId) - .locationId(LOCATION_ID) - .title(TITLE) - .content(CONTENT) - .imgUrl(IMG_URL) - .recruitmentInfo(recruitmentInfo) - .build(); + .centerId(centerId) + .locationId(LOCATION_ID) + .title(TITLE) + .content(CONTENT) + .imgUrl(IMG_URL) + .recruitmentInfo(recruitmentInfo) + .build(); } public static RecruitBoard createRecruitBoard(UUID centerId, Long locationId) { RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() - .region(REGION) - .recruitmentCount(RECRUITMENT_COUNT) - .volunteerStartDateTime(START_DATE_TIME) - .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) - .admitted(ADMITTED) - .build(); + .region(REGION) + .recruitmentCount(RECRUITMENT_COUNT) + .volunteerStartDateTime(START_DATE_TIME) + .volunteerEndDateTime(END_DATE_TIME) + .volunteerType(VOLUNTEER_TYPE) + .admitted(ADMITTED) + .build(); return RecruitBoard.builder() - .centerId(centerId) - .locationId(locationId) - .title(TITLE) - .content(CONTENT) - .imgUrl(IMG_URL) - .recruitmentInfo(recruitmentInfo) - .build(); + .centerId(centerId) + .locationId(locationId) + .title(TITLE) + .content(CONTENT) + .imgUrl(IMG_URL) + .recruitmentInfo(recruitmentInfo) + .build(); } public static RecruitBoard createRecruitBoard(String region, VolunteerType volunteerType) { RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() - .region(region) - .recruitmentCount(RECRUITMENT_COUNT) - .volunteerStartDateTime(START_DATE_TIME) - .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(volunteerType) - .admitted(ADMITTED) - .build(); + .region(region) + .recruitmentCount(RECRUITMENT_COUNT) + .volunteerStartDateTime(START_DATE_TIME) + .volunteerEndDateTime(END_DATE_TIME) + .volunteerType(volunteerType) + .admitted(ADMITTED) + .build(); return RecruitBoard.builder() - .centerId(UUID.randomUUID()) - .locationId(LOCATION_ID) - .title(TITLE) - .content(CONTENT) - .imgUrl(IMG_URL) - .recruitmentInfo(recruitmentInfo) - .build(); + .centerId(UUID.randomUUID()) + .locationId(LOCATION_ID) + .title(TITLE) + .content(CONTENT) + .imgUrl(IMG_URL) + .recruitmentInfo(recruitmentInfo) + .build(); } public static RecruitBoard createRecruitBoard(Long locationId, String title) { RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() - .region(REGION) - .recruitmentCount(RECRUITMENT_COUNT) - .volunteerStartDateTime(START_DATE_TIME) - .volunteerEndDateTime(END_DATE_TIME) - .volunteerType(VOLUNTEER_TYPE) - .admitted(ADMITTED) - .build(); + .region(REGION) + .recruitmentCount(RECRUITMENT_COUNT) + .volunteerStartDateTime(START_DATE_TIME) + .volunteerEndDateTime(END_DATE_TIME) + .volunteerType(VOLUNTEER_TYPE) + .admitted(ADMITTED) + .build(); return RecruitBoard.builder() - .centerId(UUID.randomUUID()) - .locationId(locationId) - .title(title) - .content(CONTENT) - .imgUrl(IMG_URL) - .recruitmentInfo(recruitmentInfo) - .build(); + .centerId(UUID.randomUUID()) + .locationId(locationId) + .title(title) + .content(CONTENT) + .imgUrl(IMG_URL) + .recruitmentInfo(recruitmentInfo) + .build(); + } + + public static RecruitBoard createCompletedRecruitBoard() { + + RecruitmentInfo recruitmentInfo = RecruitmentInfo.builder() + .region(REGION) + .recruitmentCount(RECRUITMENT_COUNT) + .volunteerStartDateTime(START_DATE_TIME) + .volunteerEndDateTime(END_DATE_TIME) + .volunteerType(VOLUNTEER_TYPE) + .admitted(ADMITTED) + .build(); + + RecruitBoard recruitBoard = RecruitBoard.builder() + .centerId(UUID.randomUUID()) + .locationId(LOCATION_ID) + .title(TITLE) + .content(CONTENT) + .imgUrl(IMG_URL) + .recruitmentInfo(recruitmentInfo) + .build(); + + setRecruitStatusCompleted(recruitBoard); + + return recruitBoard; + } + + private static void setRecruitStatusCompleted(RecruitBoard recruitBoard) { + try { + Field recruitStatusField = RecruitBoard.class.getDeclaredField("recruitStatus"); + recruitStatusField.setAccessible(true); // private 필드 접근 가능 설정 + recruitStatusField.set(recruitBoard, RecruitStatus.COMPLETED); // 필드 값 설정 + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException("리플렉션으로 recruitStatus를 설정하는 것에 실패했습니다", e); + } } } From 499668daf0d12e641ddbc030bae0570799decee7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 21:57:41 +0900 Subject: [PATCH 16/54] =?UTF-8?q?test(RecruitBoardRepository):=20findNotCo?= =?UTF-8?q?mpletedIdsByCenterId=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 센터 아이디로 종료되지 않았고 삭제되지 않은 RecruitBoard의 아이디 리스트를 반환 - 자동 정렬 --- .../repository/RecruitBoardRepository.java | 5 + .../RecruitBoardRepositoryImpl.java | 204 ++++++++++-------- 2 files changed, 119 insertions(+), 90 deletions(-) diff --git a/src/main/java/com/somemore/recruitboard/repository/RecruitBoardRepository.java b/src/main/java/com/somemore/recruitboard/repository/RecruitBoardRepository.java index e4082d1f2..8ca512d22 100644 --- a/src/main/java/com/somemore/recruitboard/repository/RecruitBoardRepository.java +++ b/src/main/java/com/somemore/recruitboard/repository/RecruitBoardRepository.java @@ -6,9 +6,12 @@ import com.somemore.recruitboard.repository.mapper.RecruitBoardWithLocation; import com.somemore.recruitboard.dto.condition.RecruitBoardNearByCondition; import com.somemore.recruitboard.dto.condition.RecruitBoardSearchCondition; + import java.util.List; + import java.util.Optional; import java.util.UUID; + import org.springframework.data.domain.Page; public interface RecruitBoardRepository { @@ -26,4 +29,6 @@ public interface RecruitBoardRepository { Page findAllNearby(RecruitBoardNearByCondition condition); Page findAllByCenterId(UUID centerId, RecruitBoardSearchCondition condition); + + List findNotCompletedIdsByCenterId(UUID centerId); } diff --git a/src/main/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImpl.java b/src/main/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImpl.java index 966ece64b..67d22e617 100644 --- a/src/main/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImpl.java +++ b/src/main/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImpl.java @@ -14,6 +14,9 @@ import com.somemore.location.utils.GeoUtils; import com.somemore.recruitboard.domain.QRecruitBoard; import com.somemore.recruitboard.domain.RecruitBoard; + +import java.util.List; + import com.somemore.recruitboard.domain.RecruitStatus; import com.somemore.recruitboard.domain.VolunteerType; import com.somemore.recruitboard.repository.mapper.RecruitBoardDetail; @@ -21,9 +24,10 @@ import com.somemore.recruitboard.repository.mapper.RecruitBoardWithLocation; import com.somemore.recruitboard.dto.condition.RecruitBoardNearByCondition; import com.somemore.recruitboard.dto.condition.RecruitBoardSearchCondition; -import java.util.List; + import java.util.Optional; import java.util.UUID; + import lombok.RequiredArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.springframework.data.domain.Page; @@ -54,25 +58,40 @@ public Optional findById(Long id) { QRecruitBoard recruitBoard = QRecruitBoard.recruitBoard; RecruitBoard result = queryFactory - .selectFrom(recruitBoard) - .where(isNotDeleted().and(idEq(id))) - .fetchOne(); + .selectFrom(recruitBoard) + .where(isNotDeleted().and(idEq(id))) + .fetchOne(); return Optional.ofNullable(result); } + @Override + public List findNotCompletedIdsByCenterId(UUID centerId) { + QRecruitBoard recruitBoard = QRecruitBoard.recruitBoard; + + return queryFactory + .select(recruitBoard.id) + .from(recruitBoard) + .where( + recruitBoard.centerId.eq(centerId) + .and(isNotCompleted()) + .and(isNotDeleted()) + ) + .fetch(); + } + @Override public Optional findWithLocationById(Long id) { QRecruitBoard recruitBoard = QRecruitBoard.recruitBoard; QLocation location = QLocation.location; return Optional.ofNullable( - queryFactory.select( - getRecruitBoardWithLocationConstructorExpression(recruitBoard, location)) - .from(recruitBoard) - .join(location).on(recruitBoard.locationId.eq(location.id)) - .where(isNotDeleted().and(idEq(id))) - .fetchOne()); + queryFactory.select( + getRecruitBoardWithLocationConstructorExpression(recruitBoard, location)) + .from(recruitBoard) + .join(location).on(recruitBoard.locationId.eq(location.id)) + .where(isNotDeleted().and(idEq(id))) + .fetchOne()); } @Override @@ -82,26 +101,26 @@ public Page findAllWithCenter(RecruitBoardSearchConditio Pageable pageable = condition.pageable(); BooleanExpression predicate = isNotDeleted() - .and(keywordEq(condition.keyword())) - .and(volunteerTypeEq(condition.type())) - .and(regionEq(condition.region())) - .and(admittedEq(condition.admitted())) - .and(statusEq(condition.status())); + .and(keywordEq(condition.keyword())) + .and(volunteerTypeEq(condition.type())) + .and(regionEq(condition.region())) + .and(admittedEq(condition.admitted())) + .and(statusEq(condition.status())); List content = queryFactory - .select(getRecruitBoardWithCenterConstructorExpression(recruitBoard, center)) - .from(recruitBoard) - .where(predicate) - .join(center).on(recruitBoard.centerId.eq(center.id)) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .orderBy(toOrderSpecifiers(pageable.getSort())) - .fetch(); + .select(getRecruitBoardWithCenterConstructorExpression(recruitBoard, center)) + .from(recruitBoard) + .where(predicate) + .join(center).on(recruitBoard.centerId.eq(center.id)) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(toOrderSpecifiers(pageable.getSort())) + .fetch(); JPAQuery countQuery = queryFactory - .select(recruitBoard.count()) - .from(recruitBoard) - .where(predicate); + .select(recruitBoard.count()) + .from(recruitBoard) + .where(predicate); return PageableExecutionUtils.getPage(content, pageable, countQuery::fetchOne); } @@ -115,56 +134,56 @@ public Page findAllNearby(RecruitBoardNearByCondition condit Pageable pageable = condition.pageable(); BooleanExpression predicate = isNotDeleted() - .and(locationBetween(condition)) - .and(keywordEq(condition.keyword())); + .and(locationBetween(condition)) + .and(keywordEq(condition.keyword())); List content = queryFactory - .select(getRecruitBoardDetailConstructorExpression(recruitBoard, location, center)) - .from(recruitBoard) - .join(location).on(recruitBoard.locationId.eq(location.id)) - .join(center).on(recruitBoard.centerId.eq(center.id)) - .where(predicate) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .orderBy(toOrderSpecifiers(pageable.getSort())) - .fetch(); + .select(getRecruitBoardDetailConstructorExpression(recruitBoard, location, center)) + .from(recruitBoard) + .join(location).on(recruitBoard.locationId.eq(location.id)) + .join(center).on(recruitBoard.centerId.eq(center.id)) + .where(predicate) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(toOrderSpecifiers(pageable.getSort())) + .fetch(); JPAQuery countQuery = queryFactory - .select(recruitBoard.count()) - .from(recruitBoard) - .join(location).on(recruitBoard.locationId.eq(location.id)) - .join(center).on(recruitBoard.centerId.eq(center.id)) - .where(predicate); + .select(recruitBoard.count()) + .from(recruitBoard) + .join(location).on(recruitBoard.locationId.eq(location.id)) + .join(center).on(recruitBoard.centerId.eq(center.id)) + .where(predicate); return PageableExecutionUtils.getPage(content, pageable, countQuery::fetchOne); } @Override public Page findAllByCenterId(UUID centerId, - RecruitBoardSearchCondition condition) { + RecruitBoardSearchCondition condition) { QRecruitBoard recruitBoard = QRecruitBoard.recruitBoard; Pageable pageable = condition.pageable(); BooleanExpression predicate = isNotDeleted() - .and(centerIdEq(centerId)) - .and(keywordEq(condition.keyword())) - .and(volunteerTypeEq(condition.type())) - .and(regionEq(condition.region())) - .and(admittedEq(condition.admitted())) - .and(statusEq(condition.status())); + .and(centerIdEq(centerId)) + .and(keywordEq(condition.keyword())) + .and(volunteerTypeEq(condition.type())) + .and(regionEq(condition.region())) + .and(admittedEq(condition.admitted())) + .and(statusEq(condition.status())); List content = queryFactory - .selectFrom(recruitBoard) - .where(predicate) - .offset(pageable.getOffset()) - .limit(pageable.getPageSize()) - .orderBy(toOrderSpecifiers(pageable.getSort())) - .fetch(); + .selectFrom(recruitBoard) + .where(predicate) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .orderBy(toOrderSpecifiers(pageable.getSort())) + .fetch(); JPAQuery countQuery = queryFactory - .select(recruitBoard.count()) - .from(recruitBoard) - .where(predicate); + .select(recruitBoard.count()) + .from(recruitBoard) + .where(predicate); return PageableExecutionUtils.getPage(content, pageable, countQuery::fetchOne); } @@ -181,26 +200,31 @@ private BooleanExpression isNotDeleted() { return recruitBoard.deleted.eq(false); } + private BooleanExpression isNotCompleted() { + QRecruitBoard recruitBoard = QRecruitBoard.recruitBoard; + return recruitBoard.recruitStatus.in(RecruitStatus.RECRUITING, RecruitStatus.CLOSED); + } + private BooleanExpression keywordEq(String keyword) { return StringUtils.isNotBlank(keyword) - ? recruitBoard.title.containsIgnoreCase( - keyword) : null; + ? recruitBoard.title.containsIgnoreCase( + keyword) : null; } private BooleanExpression volunteerTypeEq(VolunteerType type) { return type != null ? recruitBoard.recruitmentInfo.volunteerType.eq(type) - : null; + : null; } private BooleanExpression regionEq(String region) { return StringUtils.isNotBlank(region) - ? recruitBoard.recruitmentInfo.region.eq( - region) : null; + ? recruitBoard.recruitmentInfo.region.eq( + region) : null; } private BooleanExpression admittedEq(Boolean admitted) { return admitted != null ? recruitBoard.recruitmentInfo.admitted.eq(admitted) - : null; + : null; } private BooleanExpression statusEq(RecruitStatus status) { @@ -209,9 +233,9 @@ private BooleanExpression statusEq(RecruitStatus status) { private BooleanExpression locationBetween(RecruitBoardNearByCondition condition) { double[] coordinates = GeoUtils.calculateMaxMinCoordinates( - condition.latitude(), - condition.longitude(), - condition.radius()); + condition.latitude(), + condition.longitude(), + condition.radius()); double minLatitude = coordinates[0]; double minLongitude = coordinates[1]; @@ -219,47 +243,47 @@ private BooleanExpression locationBetween(RecruitBoardNearByCondition condition) double maxLongitude = coordinates[3]; return location.latitude.between(minLatitude, maxLatitude) - .and(location.longitude.between(minLongitude, maxLongitude)); + .and(location.longitude.between(minLongitude, maxLongitude)); } private OrderSpecifier[] toOrderSpecifiers(Sort sort) { QRecruitBoard recruitBoard = QRecruitBoard.recruitBoard; return sort.stream() - .map(order -> { - String property = order.getProperty(); - - if ("created_at".equals(property)) { - return order.isAscending() - ? recruitBoard.createdAt.asc() - : recruitBoard.createdAt.desc(); - } else if ("volunteer_start_date_time".equals(property)) { - return order.isAscending() - ? recruitBoard.recruitmentInfo.volunteerStartDateTime.asc() - : recruitBoard.recruitmentInfo.volunteerStartDateTime.desc(); - } else { - throw new IllegalStateException("Invalid sort property: " + property); - } - }) - .toArray(OrderSpecifier[]::new); + .map(order -> { + String property = order.getProperty(); + + if ("created_at".equals(property)) { + return order.isAscending() + ? recruitBoard.createdAt.asc() + : recruitBoard.createdAt.desc(); + } else if ("volunteer_start_date_time".equals(property)) { + return order.isAscending() + ? recruitBoard.recruitmentInfo.volunteerStartDateTime.asc() + : recruitBoard.recruitmentInfo.volunteerStartDateTime.desc(); + } else { + throw new IllegalStateException("Invalid sort property: " + property); + } + }) + .toArray(OrderSpecifier[]::new); } private static ConstructorExpression getRecruitBoardWithCenterConstructorExpression( - QRecruitBoard recruitBoard, QCenter center) { + QRecruitBoard recruitBoard, QCenter center) { return Projections.constructor(RecruitBoardWithCenter.class, - recruitBoard, center.name); + recruitBoard, center.name); } private static ConstructorExpression getRecruitBoardWithLocationConstructorExpression( - QRecruitBoard recruitBoard, QLocation location) { + QRecruitBoard recruitBoard, QLocation location) { return Projections.constructor(RecruitBoardWithLocation.class, - recruitBoard, location.address, location.latitude, location.longitude); + recruitBoard, location.address, location.latitude, location.longitude); } private static ConstructorExpression getRecruitBoardDetailConstructorExpression( - QRecruitBoard recruitBoard, QLocation location, QCenter center) { + QRecruitBoard recruitBoard, QLocation location, QCenter center) { return Projections.constructor(RecruitBoardDetail.class, - recruitBoard, location.address, location.latitude, location.longitude, center.name); + recruitBoard, location.address, location.latitude, location.longitude, center.name); } } From 90dd88e2a6e83ff4508a6d864bb4d0334f765a9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 22:16:57 +0900 Subject: [PATCH 17/54] =?UTF-8?q?feat(VolunteerApplyRepository):=20?= =?UTF-8?q?=EB=B4=89=EC=82=AC=20=EC=8B=A0=EC=B2=AD=20repository=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - save: 봉사 신청 데이터를 저장 - findById: 봉사 신청 ID로 조회 - findVolunteerIdsByRecruitIds: 모집글 ID 리스트로 봉사자 ID 리스트 조회 - findAllByRecruitId: 모집글 ID로 페이징된 봉사 신청 조회 - isNotDeleted: 논리 삭제된 데이터 제외 조건 추가 - toOrderSpecifiers: Sort 객체를 기반으로 정렬 조건 생성 - getCount: 페이징 처리를 위한 총 데이터 개수 조회 메서드 추가 --- .../repository/VolunteerApplyRepository.java | 17 +++ .../VolunteerApplyRepositoryImpl.java | 115 ++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepository.java create mode 100644 src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImpl.java diff --git a/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepository.java b/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepository.java new file mode 100644 index 000000000..05e55486a --- /dev/null +++ b/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepository.java @@ -0,0 +1,17 @@ +package com.somemore.volunteerApply.repository; + +import com.somemore.volunteerApply.domain.VolunteerApply; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public interface VolunteerApplyRepository { + + VolunteerApply save(VolunteerApply volunteerApply); + Optional findById(Long id); + List findVolunteerIdsByRecruitIds(List recruitIds); + Page findAllByRecruitId(Long recruitId, Pageable pageable); +} diff --git a/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImpl.java b/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImpl.java new file mode 100644 index 000000000..ed3733d02 --- /dev/null +++ b/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImpl.java @@ -0,0 +1,115 @@ +package com.somemore.volunteerApply.repository; + +import com.querydsl.core.types.OrderSpecifier; +import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.somemore.volunteerApply.domain.QVolunteerApply; +import com.somemore.volunteerApply.domain.VolunteerApply; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +@RequiredArgsConstructor +@Repository +public class VolunteerApplyRepositoryImpl implements VolunteerApplyRepository { + + private final VolunteerApplyJpaRepository volunteerApplyJpaRepository; + private final JPAQueryFactory queryFactory; + + private final QVolunteerApply volunteerApply = QVolunteerApply.volunteerApply; + + @Override + public VolunteerApply save(VolunteerApply volunteerApply) { + return volunteerApplyJpaRepository.save(volunteerApply); + } + + @Override + public Optional findById(Long id) { + return findOne(volunteerApply.id.eq(id)); + } + + @Override + public List findVolunteerIdsByRecruitIds(List recruitIds) { + + BooleanExpression exp = volunteerApply.recruitBoardId + .in(recruitIds) + .and(isNotDeleted()); + + return queryFactory + .select(volunteerApply.volunteerId) + .from(volunteerApply) + .where(exp) + .fetch(); + } + + @Override + public Page findAllByRecruitId(Long recruitId, Pageable pageable) { + + BooleanExpression exp = volunteerApply.recruitBoardId + .eq(recruitId) + .and(isNotDeleted()); + + List content = queryFactory + .selectFrom(volunteerApply) + .where(exp) + .orderBy(toOrderSpecifiers(pageable.getSort())) + .offset(pageable.getOffset()) + .limit(pageable.getPageSize()) + .fetch(); + + return new PageImpl<>( + content, + pageable, + getCount(exp) + ); + } + + private Long getCount(BooleanExpression exp) { + return queryFactory + .select(volunteerApply.count()) + .from(volunteerApply) + .where(exp) + .fetchOne(); + } + + private Optional findOne(BooleanExpression condition) { + + return Optional.ofNullable( + queryFactory + .selectFrom(volunteerApply) + .where( + condition, + isNotDeleted() + ) + .fetchOne() + ); + } + + private BooleanExpression isNotDeleted() { + return volunteerApply.deleted.isFalse(); + } + + private OrderSpecifier[] toOrderSpecifiers(Sort sort) { + + return sort.stream() + .map(order -> { + String property = order.getProperty(); + + if ("created_at".equals(property)) { + return order.isAscending() + ? volunteerApply.createdAt.asc() + : volunteerApply.createdAt.desc(); + } else { + throw new IllegalStateException("Invalid sort property: " + property); + } + }) + .toArray(OrderSpecifier[]::new); + } +} From aa4694c06a33734ebb25d123ef9a0f46585f4fb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 22:20:00 +0900 Subject: [PATCH 18/54] =?UTF-8?q?feat(RecruitBoardQueryService):=20?= =?UTF-8?q?=EA=B8=B0=EA=B4=80=20=EC=95=84=EC=9D=B4=EB=94=94=20=EA=B8=B0?= =?UTF-8?q?=EB=B0=98=EC=9C=BC=EB=A1=9C=20=EC=A2=85=EB=A3=8C=EB=90=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EC=9D=80=20RecruitBoard=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=EB=94=94=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - getNotCompletedIdsByCenterIds --- .../query/RecruitBoardQueryService.java | 31 ++++++++++++------- .../query/RecruitBoardQueryUseCase.java | 11 +++++-- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/somemore/recruitboard/service/query/RecruitBoardQueryService.java b/src/main/java/com/somemore/recruitboard/service/query/RecruitBoardQueryService.java index 112cce4a9..15047157c 100644 --- a/src/main/java/com/somemore/recruitboard/service/query/RecruitBoardQueryService.java +++ b/src/main/java/com/somemore/recruitboard/service/query/RecruitBoardQueryService.java @@ -1,13 +1,8 @@ package com.somemore.recruitboard.service.query; -import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_RECRUIT_BOARD; - import com.somemore.center.usecase.query.CenterQueryUseCase; import com.somemore.global.exception.BadRequestException; import com.somemore.recruitboard.domain.RecruitBoard; -import com.somemore.recruitboard.repository.mapper.RecruitBoardDetail; -import com.somemore.recruitboard.repository.mapper.RecruitBoardWithCenter; -import com.somemore.recruitboard.repository.mapper.RecruitBoardWithLocation; import com.somemore.recruitboard.dto.condition.RecruitBoardNearByCondition; import com.somemore.recruitboard.dto.condition.RecruitBoardSearchCondition; import com.somemore.recruitboard.dto.response.RecruitBoardDetailResponseDto; @@ -15,13 +10,20 @@ import com.somemore.recruitboard.dto.response.RecruitBoardWithCenterResponseDto; import com.somemore.recruitboard.dto.response.RecruitBoardWithLocationResponseDto; import com.somemore.recruitboard.repository.RecruitBoardRepository; +import com.somemore.recruitboard.repository.mapper.RecruitBoardDetail; +import com.somemore.recruitboard.repository.mapper.RecruitBoardWithCenter; +import com.somemore.recruitboard.repository.mapper.RecruitBoardWithLocation; import com.somemore.recruitboard.usecase.query.RecruitBoardQueryUseCase; -import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; +import java.util.UUID; + +import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_RECRUIT_BOARD; + @RequiredArgsConstructor @Transactional(readOnly = true) @Service @@ -39,38 +41,43 @@ public RecruitBoardResponseDto getById(Long id) { @Override public RecruitBoardWithLocationResponseDto getWithLocationById(Long id) { RecruitBoardWithLocation recruitBoardWithLocation = recruitBoardRepository.findWithLocationById( - id).orElseThrow( - () -> new BadRequestException(NOT_EXISTS_RECRUIT_BOARD.getMessage()) + id).orElseThrow( + () -> new BadRequestException(NOT_EXISTS_RECRUIT_BOARD.getMessage()) ); return RecruitBoardWithLocationResponseDto.from(recruitBoardWithLocation); } @Override public Page getAllWithCenter( - RecruitBoardSearchCondition condition) { + RecruitBoardSearchCondition condition) { Page boards = recruitBoardRepository.findAllWithCenter(condition); return boards.map(RecruitBoardWithCenterResponseDto::from); } @Override public Page getRecruitBoardsNearby( - RecruitBoardNearByCondition condition) { + RecruitBoardNearByCondition condition) { Page boards = recruitBoardRepository.findAllNearby(condition); return boards.map(RecruitBoardDetailResponseDto::from); } @Override public Page getRecruitBoardsByCenterId(UUID centerId, - RecruitBoardSearchCondition condition) { + RecruitBoardSearchCondition condition) { centerQueryUseCase.validateCenterExists(centerId); Page boards = recruitBoardRepository.findAllByCenterId(centerId, condition); return boards.map(RecruitBoardResponseDto::from); } + @Override + public List getNotCompletedIdsByCenterIds(UUID centerId) { + return recruitBoardRepository.findNotCompletedIdsByCenterId(centerId); + } + private RecruitBoard getRecruitBoard(Long id) { return recruitBoardRepository.findById(id).orElseThrow( - () -> new BadRequestException(NOT_EXISTS_RECRUIT_BOARD.getMessage()) + () -> new BadRequestException(NOT_EXISTS_RECRUIT_BOARD.getMessage()) ); } } diff --git a/src/main/java/com/somemore/recruitboard/usecase/query/RecruitBoardQueryUseCase.java b/src/main/java/com/somemore/recruitboard/usecase/query/RecruitBoardQueryUseCase.java index 708df7097..4ce52f9b6 100644 --- a/src/main/java/com/somemore/recruitboard/usecase/query/RecruitBoardQueryUseCase.java +++ b/src/main/java/com/somemore/recruitboard/usecase/query/RecruitBoardQueryUseCase.java @@ -6,9 +6,11 @@ import com.somemore.recruitboard.dto.response.RecruitBoardResponseDto; import com.somemore.recruitboard.dto.response.RecruitBoardWithCenterResponseDto; import com.somemore.recruitboard.dto.response.RecruitBoardWithLocationResponseDto; -import java.util.UUID; import org.springframework.data.domain.Page; +import java.util.List; +import java.util.UUID; + public interface RecruitBoardQueryUseCase { RecruitBoardResponseDto getById(Long id); @@ -18,8 +20,11 @@ public interface RecruitBoardQueryUseCase { Page getAllWithCenter(RecruitBoardSearchCondition condition); Page getRecruitBoardsNearby( - RecruitBoardNearByCondition condition); + RecruitBoardNearByCondition condition); Page getRecruitBoardsByCenterId(UUID centerId, - RecruitBoardSearchCondition condition); + RecruitBoardSearchCondition condition); + + List getNotCompletedIdsByCenterIds(UUID centerId); + } From 4d66f16ff05a39ffedcaf7c17dfb43ad95b52155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 22:22:45 +0900 Subject: [PATCH 19/54] =?UTF-8?q?feat(VolunteerApplyJpaRepository):=20JpaR?= =?UTF-8?q?epo=20=EC=83=81=EC=86=8D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/VolunteerApplyJpaRepository.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyJpaRepository.java diff --git a/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyJpaRepository.java b/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyJpaRepository.java new file mode 100644 index 000000000..1b51573ec --- /dev/null +++ b/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyJpaRepository.java @@ -0,0 +1,7 @@ +package com.somemore.volunteerApply.repository; + +import com.somemore.volunteerApply.domain.VolunteerApply; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface VolunteerApplyJpaRepository extends JpaRepository { +} From 5402867cb58dc25d23b82706ca4b06a219e58dcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 22:24:05 +0900 Subject: [PATCH 20/54] =?UTF-8?q?feat(VolunteerQueryService):=20=EB=8B=89?= =?UTF-8?q?=EB=84=A4=EC=9E=84=20=EC=A1=B0=ED=9A=8C=20=EA=B0=92=20null=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../volunteer/service/VolunteerQueryService.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java b/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java index 12fe4a64e..0fbd94e11 100644 --- a/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java +++ b/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java @@ -1,5 +1,6 @@ package com.somemore.volunteer.service; +import com.somemore.facade.validator.VolunteerDetailAccessValidator; import com.somemore.global.exception.BadRequestException; import com.somemore.volunteer.domain.Volunteer; import com.somemore.volunteer.domain.VolunteerDetail; @@ -24,6 +25,7 @@ public class VolunteerQueryService implements VolunteerQueryUseCase { private final VolunteerRepository volunteerRepository; private final VolunteerDetailRepository volunteerDetailRepository; + private final VolunteerDetailAccessValidator volunteerDetailAccessValidator; @Override public VolunteerResponseDto getMyProfile(UUID volunteerId) { @@ -62,7 +64,13 @@ public UUID getVolunteerIdByOAuthId(String oAuthId) { @Override public String getNicknameById(UUID id) { - return volunteerRepository.findNicknameById(id); + String nickname = volunteerRepository.findNicknameById(id); + + if (nickname == null || nickname.isBlank()) { + throw new BadRequestException(NOT_EXISTS_VOLUNTEER); + } + + return nickname; } private Volunteer findVolunteer(UUID volunteerId) { From 2734cdc5f5f777f5fffd1e36f04b363a0a5016b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 22:25:18 +0900 Subject: [PATCH 21/54] =?UTF-8?q?feat(VolunteerApplyQueryService):=20?= =?UTF-8?q?=EB=B4=89=EC=82=AC=20=EC=8B=A0=EC=B2=AD=20Query=20Service/UseCa?= =?UTF-8?q?se=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - getVolunteerIdsByRecruitIds: 모집글 ID 리스트로 봉사자 ID 리스트 조회 --- .../service/VolunteerApplyQueryService.java | 25 +++++++++++++++++++ .../usecase/VolunteerApplyQueryUseCase.java | 9 +++++++ 2 files changed, 34 insertions(+) create mode 100644 src/main/java/com/somemore/volunteerApply/service/VolunteerApplyQueryService.java create mode 100644 src/main/java/com/somemore/volunteerApply/usecase/VolunteerApplyQueryUseCase.java diff --git a/src/main/java/com/somemore/volunteerApply/service/VolunteerApplyQueryService.java b/src/main/java/com/somemore/volunteerApply/service/VolunteerApplyQueryService.java new file mode 100644 index 000000000..5b36013cc --- /dev/null +++ b/src/main/java/com/somemore/volunteerApply/service/VolunteerApplyQueryService.java @@ -0,0 +1,25 @@ +package com.somemore.volunteerApply.service; + +import com.somemore.volunteerApply.repository.VolunteerApplyRepository; +import com.somemore.volunteerApply.usecase.VolunteerApplyQueryUseCase; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.UUID; + +@Slf4j +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class VolunteerApplyQueryService implements VolunteerApplyQueryUseCase { + + private final VolunteerApplyRepository volunteerApplyRepository; + @Override + public List getVolunteerIdsByRecruitIds(List recruitIds) { + + return volunteerApplyRepository.findVolunteerIdsByRecruitIds(recruitIds); + } +} diff --git a/src/main/java/com/somemore/volunteerApply/usecase/VolunteerApplyQueryUseCase.java b/src/main/java/com/somemore/volunteerApply/usecase/VolunteerApplyQueryUseCase.java new file mode 100644 index 000000000..e1795ef83 --- /dev/null +++ b/src/main/java/com/somemore/volunteerApply/usecase/VolunteerApplyQueryUseCase.java @@ -0,0 +1,9 @@ +package com.somemore.volunteerApply.usecase; + +import java.util.List; +import java.util.UUID; + +public interface VolunteerApplyQueryUseCase { + + List getVolunteerIdsByRecruitIds(List recruitIds); +} From 542dc3699c13a3ebdfe9e32568824ebcad34c95d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 22:29:40 +0900 Subject: [PATCH 22/54] =?UTF-8?q?test:=20tearDown=EC=9D=84=20@Transactiona?= =?UTF-8?q?l=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../volunteer/service/RegisterVolunteerServiceTest.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/test/java/com/somemore/volunteer/service/RegisterVolunteerServiceTest.java b/src/test/java/com/somemore/volunteer/service/RegisterVolunteerServiceTest.java index 543718d3a..804744903 100644 --- a/src/test/java/com/somemore/volunteer/service/RegisterVolunteerServiceTest.java +++ b/src/test/java/com/somemore/volunteer/service/RegisterVolunteerServiceTest.java @@ -10,13 +10,14 @@ import com.somemore.volunteer.repository.VolunteerDetailRepository; import com.somemore.volunteer.repository.VolunteerRepository; import jakarta.persistence.EntityNotFoundException; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; import static org.assertj.core.api.Assertions.assertThat; +@Transactional class RegisterVolunteerServiceTest extends IntegrationTestSupport { @Autowired @@ -28,12 +29,6 @@ class RegisterVolunteerServiceTest extends IntegrationTestSupport { @Autowired private VolunteerDetailRepository volunteerDetailRepository; - @AfterEach - void tearDown() { - volunteerRepository.deleteAllInBatch(); - volunteerDetailRepository.deleteAllInBatch(); - } - @DisplayName("봉사자와 상세 정보를 저장한다") @Test void registerVolunteer() { From 5baca67189d01c0db1986aea8ee0064abd9e532c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 23:26:26 +0900 Subject: [PATCH 23/54] =?UTF-8?q?feat(VolunteerDetailAccessValidator):=20?= =?UTF-8?q?=EB=B4=89=EC=82=AC=EC=9E=90=20=EC=83=81=EC=84=B8=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=A0=91=EA=B7=BC=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 완료되지 않은 모집글 ID 조회 및 봉사자 ID와의 매칭 검증 - 타겟 봉사자 ID가 모집글과 연관되지 않은 경우 예외 처리 - RecruitBoardQueryUseCase와 VolunteerApplyQueryUseCase를 활용 --- .../VolunteerDetailAccessValidator.java | 8 +++++ .../VolunteerDetailAccessValidatorImpl.java | 35 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidator.java create mode 100644 src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImpl.java diff --git a/src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidator.java b/src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidator.java new file mode 100644 index 000000000..9d7a5601f --- /dev/null +++ b/src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidator.java @@ -0,0 +1,8 @@ +package com.somemore.facade.validator; + +import java.util.UUID; + +public interface VolunteerDetailAccessValidator { + + void validateByCenterId(UUID centerId, UUID targetVolunteerId); +} diff --git a/src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImpl.java b/src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImpl.java new file mode 100644 index 000000000..218d598ec --- /dev/null +++ b/src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImpl.java @@ -0,0 +1,35 @@ +package com.somemore.facade.validator; + +import com.somemore.global.exception.BadRequestException; +import com.somemore.recruitboard.usecase.query.RecruitBoardQueryUseCase; +import com.somemore.volunteerApply.usecase.VolunteerApplyQueryUseCase; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.UUID; + +import static com.somemore.global.exception.ExceptionMessage.UNAUTHORIZED_VOLUNTEER_DETAIL; + +@Component +@RequiredArgsConstructor +public class VolunteerDetailAccessValidatorImpl implements VolunteerDetailAccessValidator { + + private final RecruitBoardQueryUseCase recruitBoardQueryUseCase; + private final VolunteerApplyQueryUseCase volunteerApplyQueryUseCase; + + /** + * 기관 ID를 기반으로 완료되지 않은 모집글들의 ID를 조회하고, + * 해당 모집글들에 연관된 봉사자들의 ID 목록에 타겟 봉사자 ID가 포함되어 있는지 검증. + */ + public void validateByCenterId(UUID centerId, UUID targetVolunteerId) { + List allNotCompletedIdsByCenterId = recruitBoardQueryUseCase.getNotCompletedIdsByCenterIds(centerId); + + List volunteerIdsByRecruitIds = volunteerApplyQueryUseCase.getVolunteerIdsByRecruitIds(allNotCompletedIdsByCenterId); + + volunteerIdsByRecruitIds.stream() + .filter(volunteerId -> volunteerId.equals(targetVolunteerId)) + .findAny() + .orElseThrow(() -> new BadRequestException(UNAUTHORIZED_VOLUNTEER_DETAIL)); + } +} \ No newline at end of file From 84d7b877e2cdf37bd864c8a5f5d916b166c5de20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 23:36:35 +0900 Subject: [PATCH 24/54] =?UTF-8?q?test(RecruitBoardQueryService):=20?= =?UTF-8?q?=EC=84=BC=ED=84=B0=20=EC=95=84=EC=9D=B4=EB=94=94=EB=A1=9C=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=EB=90=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20?= =?UTF-8?q?=EB=AA=A8=EC=A7=91=20=EA=B2=8C=EC=8B=9C=EA=B8=80=EC=9D=98=20ID?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../query/RecruitBoardQueryServiceTest.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/test/java/com/somemore/recruitboard/service/query/RecruitBoardQueryServiceTest.java b/src/test/java/com/somemore/recruitboard/service/query/RecruitBoardQueryServiceTest.java index d42f6de9c..89ee5d8bd 100644 --- a/src/test/java/com/somemore/recruitboard/service/query/RecruitBoardQueryServiceTest.java +++ b/src/test/java/com/somemore/recruitboard/service/query/RecruitBoardQueryServiceTest.java @@ -1,7 +1,9 @@ package com.somemore.recruitboard.service.query; import static com.somemore.common.fixture.CenterFixture.createCenter; +import static com.somemore.common.fixture.LocalDateTimeFixture.createCurrentDateTime; import static com.somemore.common.fixture.LocationFixture.createLocation; +import static com.somemore.common.fixture.RecruitBoardFixture.createCompletedRecruitBoard; import static com.somemore.common.fixture.RecruitBoardFixture.createRecruitBoard; import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_CENTER; import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_RECRUIT_BOARD; @@ -15,6 +17,7 @@ import com.somemore.location.domain.Location; import com.somemore.location.repository.LocationRepository; import com.somemore.recruitboard.domain.RecruitBoard; +import com.somemore.recruitboard.domain.RecruitStatus; import com.somemore.recruitboard.dto.condition.RecruitBoardNearByCondition; import com.somemore.recruitboard.dto.condition.RecruitBoardSearchCondition; import com.somemore.recruitboard.dto.response.RecruitBoardDetailResponseDto; @@ -215,6 +218,49 @@ void getRecruitBoardsByCenterIdWhenNotExistsCenterId() { .hasMessage(NOT_EXISTS_CENTER.getMessage()); } + @DisplayName("센터 ID로 완료되지 않은 모집 게시글들의 ID를 조회할 수 있다") + @Test + void findNotCompletedIdsByCenterIds() { + // given + UUID centerId = UUID.randomUUID(); + + RecruitBoard deletedRecruitingBoard = createRecruitBoard(centerId); + deletedRecruitingBoard.markAsDeleted(); + recruitBoardRepository.save(deletedRecruitingBoard); + + RecruitBoard recruitingBoard = createRecruitBoard(centerId); + recruitBoardRepository.save(recruitingBoard); + + RecruitBoard deletedClosedBoard = createRecruitBoard(centerId); + deletedClosedBoard.changeRecruitStatus(RecruitStatus.CLOSED, createCurrentDateTime()); + deletedClosedBoard.markAsDeleted(); + recruitBoardRepository.save(deletedClosedBoard); + + RecruitBoard closedBoard = createRecruitBoard(centerId); + closedBoard.changeRecruitStatus(RecruitStatus.CLOSED, createCurrentDateTime()); + recruitBoardRepository.save(closedBoard); + + RecruitBoard deletedCompletedRecruitBoard = createCompletedRecruitBoard(); + deletedCompletedRecruitBoard.markAsDeleted(); + recruitBoardRepository.save(deletedCompletedRecruitBoard); + + RecruitBoard completedRecruitBoard = createCompletedRecruitBoard(); + recruitBoardRepository.save(completedRecruitBoard); + + // when + List notCompletedBoardIds = recruitBoardQueryService.getNotCompletedIdsByCenterIds(centerId); + + // then + assertThat(notCompletedBoardIds) + .hasSize(2); + + assertThat(notCompletedBoardIds) + .doesNotContain(deletedRecruitingBoard.getId()) + .doesNotContain(deletedClosedBoard.getId()) + .doesNotContain(deletedCompletedRecruitBoard.getId()) + .doesNotContain(completedRecruitBoard.getId()); + } + private Pageable getPageable() { Sort sort = Sort.by(Sort.Order.desc("created_at")); return PageRequest.of(0, 5, sort); From bde83d469cfa3fd5c7d3624f597b8b38d88c2c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 23:37:19 +0900 Subject: [PATCH 25/54] =?UTF-8?q?test(RecruitBoardQueryRepository):=20?= =?UTF-8?q?=EC=84=BC=ED=84=B0=20=EC=95=84=EC=9D=B4=EB=94=94=EB=A1=9C=20?= =?UTF-8?q?=EC=99=84=EB=A3=8C=EB=90=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20?= =?UTF-8?q?=EB=AA=A8=EC=A7=91=20=EA=B2=8C=EC=8B=9C=EA=B8=80=EC=9D=98=20ID?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RecruitBoardRepositoryImplTest.java | 160 +++++++++++------- 1 file changed, 98 insertions(+), 62 deletions(-) diff --git a/src/test/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImplTest.java b/src/test/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImplTest.java index 146393248..5fe2b731b 100644 --- a/src/test/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImplTest.java +++ b/src/test/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImplTest.java @@ -1,13 +1,5 @@ package com.somemore.recruitboard.repository; -import static com.somemore.common.fixture.CenterFixture.createCenter; -import static com.somemore.common.fixture.LocalDateTimeFixture.createCurrentDateTime; -import static com.somemore.common.fixture.LocationFixture.createLocation; -import static com.somemore.common.fixture.RecruitBoardFixture.createRecruitBoard; -import static com.somemore.recruitboard.domain.RecruitStatus.CLOSED; -import static com.somemore.recruitboard.domain.VolunteerType.ADMINISTRATIVE_SUPPORT; -import static org.assertj.core.api.Assertions.assertThat; - import com.somemore.IntegrationTestSupport; import com.somemore.center.domain.Center; import com.somemore.center.repository.CenterRepository; @@ -16,16 +8,11 @@ import com.somemore.recruitboard.domain.RecruitBoard; import com.somemore.recruitboard.domain.RecruitStatus; import com.somemore.recruitboard.domain.VolunteerType; +import com.somemore.recruitboard.dto.condition.RecruitBoardNearByCondition; +import com.somemore.recruitboard.dto.condition.RecruitBoardSearchCondition; import com.somemore.recruitboard.repository.mapper.RecruitBoardDetail; import com.somemore.recruitboard.repository.mapper.RecruitBoardWithCenter; import com.somemore.recruitboard.repository.mapper.RecruitBoardWithLocation; -import com.somemore.recruitboard.dto.condition.RecruitBoardNearByCondition; -import com.somemore.recruitboard.dto.condition.RecruitBoardSearchCondition; -import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.UUID; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -36,6 +23,21 @@ import org.springframework.data.domain.Sort; import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static com.somemore.common.fixture.CenterFixture.createCenter; +import static com.somemore.common.fixture.LocalDateTimeFixture.createCurrentDateTime; +import static com.somemore.common.fixture.LocationFixture.createLocation; +import static com.somemore.common.fixture.RecruitBoardFixture.createCompletedRecruitBoard; +import static com.somemore.common.fixture.RecruitBoardFixture.createRecruitBoard; +import static com.somemore.recruitboard.domain.RecruitStatus.CLOSED; +import static com.somemore.recruitboard.domain.VolunteerType.ADMINISTRATIVE_SUPPORT; +import static org.assertj.core.api.Assertions.assertThat; + @Transactional class RecruitBoardRepositoryImplTest extends IntegrationTestSupport { @@ -96,7 +98,7 @@ void findWithCenterByIdWithNotExistId() { // when Optional findOne = recruitBoardRepository.findWithLocationById( - deletedRecruitBoard.getId()); + deletedRecruitBoard.getId()); // then assertThat(findOne).isEmpty(); @@ -109,8 +111,8 @@ void findAllWithCenterWithoutCriteria() { Pageable pageable = getPageable(); RecruitBoardSearchCondition condition = RecruitBoardSearchCondition.builder() - .pageable(pageable) - .build(); + .pageable(pageable) + .build(); // when Page result = recruitBoardRepository.findAllWithCenter(condition); @@ -123,7 +125,7 @@ void findAllWithCenterWithoutCriteria() { assertThat(result.getContent()).hasSize(5); assertThat(result.getContent().get(0).recruitBoard().getCreatedAt()) - .isAfterOrEqualTo(result.getContent().get(1).recruitBoard().getCreatedAt()); + .isAfterOrEqualTo(result.getContent().get(1).recruitBoard().getCreatedAt()); } @DisplayName("키워드로 조회할 수 있다") @@ -138,9 +140,9 @@ void findAllWithCenterByKeyword() { Pageable pageable = getPageable(); RecruitBoardSearchCondition condition = RecruitBoardSearchCondition.builder() - .keyword(keyword) - .pageable(pageable) - .build(); + .keyword(keyword) + .pageable(pageable) + .build(); // when Page result = recruitBoardRepository.findAllWithCenter(condition); @@ -153,7 +155,7 @@ void findAllWithCenterByKeyword() { assertThat(result.getContent()).hasSize(1); assertThat(result.getContent().getFirst().recruitBoard().getTitle()) - .isEqualTo("키워드 조회 제목"); + .isEqualTo("키워드 조회 제목"); } @DisplayName("봉사활동 유형으로 조회할 수 있다") @@ -169,9 +171,9 @@ void findAllWithCenterByType() { Pageable pageable = getPageable(); VolunteerType type = ADMINISTRATIVE_SUPPORT; RecruitBoardSearchCondition condition = RecruitBoardSearchCondition.builder() - .type(type) - .pageable(pageable) - .build(); + .type(type) + .pageable(pageable) + .build(); // when Page result = recruitBoardRepository.findAllWithCenter(condition); @@ -184,7 +186,7 @@ void findAllWithCenterByType() { assertThat(result.getContent()).hasSize(1); assertThat(result.getContent().getFirst().recruitBoard().getRecruitmentInfo() - .getVolunteerType()).isEqualTo(type); + .getVolunteerType()).isEqualTo(type); } @DisplayName("지역으로 조회할 수 있다") @@ -202,22 +204,56 @@ void findAllWithCenterByRegion() { Pageable pageable = getPageable(); RecruitBoardSearchCondition condition = RecruitBoardSearchCondition.builder() - .region(region) - .pageable(pageable) - .build(); + .region(region) + .pageable(pageable) + .build(); // when Page result = recruitBoardRepository.findAllWithCenter(condition); - // then - assertThat(result).isNotNull(); - assertThat(result.getTotalElements()).isEqualTo(1); - assertThat(result.getSize()).isEqualTo(5); - assertThat(result.getNumber()).isZero(); - assertThat(result.getContent()).hasSize(1); + } - assertThat(result.getContent().getFirst().recruitBoard().getRecruitmentInfo() - .getRegion()).isEqualTo(region); + @DisplayName("센터 ID로 완료되지 않은 모집 게시글들의 ID를 조회할 수 있다") + @Test + void findNotCompletedIdsByCenterIds() { + // given + UUID centerId = UUID.randomUUID(); + + RecruitBoard deletedRecruitingBoard = createRecruitBoard(centerId); + deletedRecruitingBoard.markAsDeleted(); + recruitBoardRepository.save(deletedRecruitingBoard); + + RecruitBoard recruitingBoard = createRecruitBoard(centerId); + recruitBoardRepository.save(recruitingBoard); + + RecruitBoard deletedClosedBoard = createRecruitBoard(centerId); + deletedClosedBoard.changeRecruitStatus(RecruitStatus.CLOSED, createCurrentDateTime()); + deletedClosedBoard.markAsDeleted(); + recruitBoardRepository.save(deletedClosedBoard); + + RecruitBoard closedBoard = createRecruitBoard(centerId); + closedBoard.changeRecruitStatus(RecruitStatus.CLOSED, createCurrentDateTime()); + recruitBoardRepository.save(closedBoard); + + RecruitBoard deletedCompletedRecruitBoard = createCompletedRecruitBoard(); + deletedCompletedRecruitBoard.markAsDeleted(); + recruitBoardRepository.save(deletedCompletedRecruitBoard); + + RecruitBoard completedRecruitBoard = createCompletedRecruitBoard(); + recruitBoardRepository.save(completedRecruitBoard); + + // when + List notCompletedBoardIds = recruitBoardRepository.findNotCompletedIdsByCenterId(centerId); + + // then + assertThat(notCompletedBoardIds) + .hasSize(2); + + assertThat(notCompletedBoardIds) + .doesNotContain(deletedRecruitingBoard.getId()) + .doesNotContain(deletedClosedBoard.getId()) + .doesNotContain(deletedCompletedRecruitBoard.getId()) + .doesNotContain(completedRecruitBoard.getId()); } @DisplayName("시간 인증 여부로 조회할 수 있다") @@ -234,9 +270,9 @@ void findAllWithCenterByAdmitted() { Pageable pageable = getPageable(); RecruitBoardSearchCondition condition = RecruitBoardSearchCondition.builder() - .admitted(false) - .pageable(pageable) - .build(); + .admitted(false) + .pageable(pageable) + .build(); // when Page result = recruitBoardRepository.findAllWithCenter(condition); @@ -249,7 +285,7 @@ void findAllWithCenterByAdmitted() { assertThat(result.getContent()).hasSize(1); assertThat(result.getContent().getFirst().recruitBoard().getRecruitmentInfo() - .getAdmitted()).isFalse(); + .getAdmitted()).isFalse(); } @DisplayName("모집글 상태로 조회할 수 있다.") @@ -268,9 +304,9 @@ void findAllWithCenterByStatus() { Pageable pageable = getPageable(); RecruitBoardSearchCondition condition = RecruitBoardSearchCondition.builder() - .status(status) - .pageable(pageable) - .build(); + .status(status) + .pageable(pageable) + .build(); // when Page result = recruitBoardRepository.findAllWithCenter(condition); @@ -283,7 +319,7 @@ void findAllWithCenterByStatus() { assertThat(result.getContent()).hasSize(1); assertThat(result.getContent().getFirst().recruitBoard().getRecruitStatus()).isEqualTo( - status); + status); } @DisplayName("위치 기반으로 반경 내에 모집글을 반환한다") @@ -293,11 +329,11 @@ void findAllNearByLocation() { Pageable pageable = getPageable(); RecruitBoardNearByCondition condition = RecruitBoardNearByCondition.builder() - .latitude(37.5935) - .longitude(126.9780) - .radius(5.0) - .pageable(pageable) - .build(); + .latitude(37.5935) + .longitude(126.9780) + .radius(5.0) + .pageable(pageable) + .build(); // when Page result = recruitBoardRepository.findAllNearby(condition); @@ -315,11 +351,11 @@ void findAllNearByLocation_noResult() { Pageable pageable = getPageable(); RecruitBoardNearByCondition condition = RecruitBoardNearByCondition.builder() - .latitude(37.6115) - .longitude(127.034) - .radius(5.0) - .pageable(pageable) - .build(); + .latitude(37.6115) + .longitude(127.034) + .radius(5.0) + .pageable(pageable) + .build(); // when Page result = recruitBoardRepository.findAllNearby(condition); @@ -343,12 +379,12 @@ void findAllByCenterId() { Pageable pageable = getPageable(); RecruitBoardSearchCondition condition = RecruitBoardSearchCondition.builder() - .pageable(pageable) - .build(); + .pageable(pageable) + .build(); // when Page result = recruitBoardRepository.findAllByCenterId(center.getId(), - condition); + condition); // then assertThat(result).isNotEmpty(); @@ -363,12 +399,12 @@ void findAllByCenterIdWhenWrongCenterId() { UUID centerId = UUID.randomUUID(); Pageable pageable = getPageable(); RecruitBoardSearchCondition condition = RecruitBoardSearchCondition.builder() - .pageable(pageable) - .build(); + .pageable(pageable) + .build(); // when Page results = recruitBoardRepository.findAllByCenterId(centerId, - condition); + condition); // then assertThat(results).isEmpty(); From 2919f35224a2a43d95d10d1b5652d84dd482e23f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 23:38:16 +0900 Subject: [PATCH 26/54] =?UTF-8?q?test(VolunteerApplyQueryService):=20?= =?UTF-8?q?=EB=AA=A8=EC=A7=91=20=EC=95=84=EC=9D=B4=EB=94=94=EB=A1=9C=20?= =?UTF-8?q?=EB=B4=89=EC=82=AC=EC=9E=90=20=EC=95=84=EC=9D=B4=EB=94=94=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=A1=B0=ED=9A=8C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VolunteerApplyQueryServiceTest.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/test/java/com/somemore/volunteerApply/service/VolunteerApplyQueryServiceTest.java diff --git a/src/test/java/com/somemore/volunteerApply/service/VolunteerApplyQueryServiceTest.java b/src/test/java/com/somemore/volunteerApply/service/VolunteerApplyQueryServiceTest.java new file mode 100644 index 000000000..4c53a37cb --- /dev/null +++ b/src/test/java/com/somemore/volunteerApply/service/VolunteerApplyQueryServiceTest.java @@ -0,0 +1,57 @@ +package com.somemore.volunteerApply.service; + +import com.somemore.IntegrationTestSupport; +import com.somemore.volunteerApply.domain.VolunteerApply; +import com.somemore.volunteerApply.repository.VolunteerApplyRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + +@Transactional +class VolunteerApplyQueryServiceTest extends IntegrationTestSupport { + + @Autowired + private VolunteerApplyQueryService volunteerApplyQueryService; + + @Autowired + private VolunteerApplyRepository volunteerApplyRepository; + + @DisplayName("recruitIds로 봉사자 ID 리스트를 조회할 수 있다") + @Test + void getVolunteerIdsByRecruitIds() { + // Given + Long recruitId1 = 1L; + Long recruitId2 = 2L; + UUID volunteerId1 = UUID.randomUUID(); + UUID volunteerId2 = UUID.randomUUID(); + + VolunteerApply apply1 = createVolunteerApply(recruitId1, volunteerId1); + VolunteerApply apply2 = createVolunteerApply(recruitId2, volunteerId2); + + volunteerApplyRepository.save(apply1); + volunteerApplyRepository.save(apply2); + + // When + List volunteerIds = volunteerApplyQueryService.getVolunteerIdsByRecruitIds(List.of(recruitId1, recruitId2)); + + // Then + assertThat(volunteerIds) + .hasSize(2) + .containsExactlyInAnyOrder(volunteerId1, volunteerId2); + } + + private VolunteerApply createVolunteerApply(Long recruitId, UUID volunteerId) { + return VolunteerApply.builder() + .volunteerId(volunteerId) + .recruitBoardId(recruitId) + .status(null) + .attended(null) + .build(); + } +} \ No newline at end of file From a3d5cec5e4588f9996fbbdbca999fe62abc2d5e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 23:39:21 +0900 Subject: [PATCH 27/54] =?UTF-8?q?test(VolunteerApplyRepository):=20?= =?UTF-8?q?=EB=B4=89=EC=82=AC=20=EC=8B=A0=EC=B2=AD/=EC=A1=B0=ED=9A=8C,=20?= =?UTF-8?q?=EB=AA=A8=EC=A7=91=20ID=EB=A1=9C=20=EB=B4=89=EC=82=AC=EC=9E=90?= =?UTF-8?q?=20ID=20=EB=A6=AC=EC=8A=A4=ED=8A=B8/=ED=8E=98=EC=9D=B4=EC=A7=95?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VolunteerApplyRepositoryImplTest.java | 104 ++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/test/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImplTest.java diff --git a/src/test/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImplTest.java b/src/test/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImplTest.java new file mode 100644 index 000000000..cb296420d --- /dev/null +++ b/src/test/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImplTest.java @@ -0,0 +1,104 @@ +package com.somemore.volunteerApply.repository; + +import com.somemore.IntegrationTestSupport; +import com.somemore.volunteerApply.domain.VolunteerApply; +import com.somemore.volunteerApply.domain.ApplyStatus; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + +@Transactional +class VolunteerApplyRepositoryImplTest extends IntegrationTestSupport { + + @Autowired + private VolunteerApplyRepositoryImpl volunteerApplyRepository; + + @BeforeEach + void setUp() { + // Given + for (int i = 1; i <= 15; i++) { + VolunteerApply apply = VolunteerApply.builder() + .volunteerId(UUID.randomUUID()) + .recruitBoardId(1L) + .status(ApplyStatus.WAITING) + .attended(false) + .build(); + volunteerApplyRepository.save(apply); + } + + for (int i = 1; i <= 5; i++) { + VolunteerApply apply = VolunteerApply.builder() + .volunteerId(UUID.randomUUID()) + .recruitBoardId(2L) + .status(ApplyStatus.APPROVED) + .attended(true) + .build(); + volunteerApplyRepository.save(apply); + } + } + + @DisplayName("봉사 신청 저장 및 조회") + @Test + void saveAndFindById() { + // Given + VolunteerApply newApply = VolunteerApply.builder() + .volunteerId(UUID.randomUUID()) + .recruitBoardId(1L) + .status(ApplyStatus.APPROVED) + .attended(false) + .build(); + VolunteerApply savedApply = volunteerApplyRepository.save(newApply); + + // When + Optional foundApply = volunteerApplyRepository.findById(savedApply.getId()); + + // Then + assertThat(foundApply).isPresent(); + assertThat(foundApply.get().getId()).isEqualTo(savedApply.getId()); + assertThat(foundApply.get().getStatus()).isEqualTo(ApplyStatus.APPROVED); + } + + @DisplayName("모집글 ID 리스트로 봉사자 ID 리스트 조회") + @Test + void findVolunteerIdsByRecruitIds() { + // When + List volunteerIds = volunteerApplyRepository.findVolunteerIdsByRecruitIds(List.of(1L, 2L)); + + // Then + assertThat(volunteerIds).hasSize(20); + } + + @DisplayName("모집글 ID로 페이징된 봉사 신청 조회") + @Test + void findAllByRecruitId() { + // Given + PageRequest firstPage = PageRequest.of(0, 10, Sort.by(Sort.Order.asc("created_at"))); + PageRequest secondPage = PageRequest.of(1, 10, Sort.by(Sort.Order.asc("created_at"))); + + // When + Page firstPageResult = volunteerApplyRepository.findAllByRecruitId(1L, firstPage); + Page secondPageResult = volunteerApplyRepository.findAllByRecruitId(1L, secondPage); + + // Then + assertThat(firstPageResult.getContent()).hasSize(10); + assertThat(firstPageResult.getTotalElements()).isEqualTo(15); + assertThat(firstPageResult.getTotalPages()).isEqualTo(2); + assertThat(firstPageResult.hasNext()).isTrue(); + assertThat(firstPageResult.hasPrevious()).isFalse(); + + assertThat(secondPageResult.getContent()).hasSize(5); + assertThat(secondPageResult.hasNext()).isFalse(); + assertThat(secondPageResult.hasPrevious()).isTrue(); + } +} \ No newline at end of file From 943ce649a105f9a83ab0a259b580f46d2de977bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 23:40:11 +0900 Subject: [PATCH 28/54] =?UTF-8?q?test(VolunteerDetailRepository):=20?= =?UTF-8?q?=EB=B4=89=EC=82=AC=EC=9E=90=20ID=EB=A1=9C=20=EB=B4=89=EC=82=AC?= =?UTF-8?q?=EC=9E=90=20=EC=83=81=EC=84=B8=20=EC=A0=95=EB=B3=B4=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C/=EC=A0=80=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VolunteerDetailRepositoryImplTest.java | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 src/test/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImplTest.java diff --git a/src/test/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImplTest.java b/src/test/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImplTest.java new file mode 100644 index 000000000..0f09c3b8a --- /dev/null +++ b/src/test/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImplTest.java @@ -0,0 +1,66 @@ +package com.somemore.volunteer.repository; + +import com.somemore.IntegrationTestSupport; +import com.somemore.volunteer.domain.Gender; +import com.somemore.volunteer.domain.VolunteerDetail; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; + +@Transactional +class VolunteerDetailRepositoryTest extends IntegrationTestSupport { + + @Autowired + private VolunteerDetailRepository volunteerDetailRepository; + + @DisplayName("봉사자 ID로 봉사자 상세 정보를 조회한다.") + @Test + void findByVolunteerId() { + // given + UUID volunteerId = UUID.randomUUID(); + VolunteerDetail volunteerDetail = createVolunteerDetail(volunteerId); + + volunteerDetailRepository.save(volunteerDetail); + + // when + Optional foundDetail = volunteerDetailRepository.findByVolunteerId(volunteerId); + + // then + assertThat(foundDetail).isPresent(); + assertThat(foundDetail.get().getVolunteerId()).isEqualTo(volunteerId); + assertThat(foundDetail.get().getName()).isEqualTo(volunteerDetail.getName()); + } + + @DisplayName("봉사자 상세 정보를 저장한다.") + @Test + void saveVolunteerDetail() { + // given + UUID volunteerId = UUID.randomUUID(); + VolunteerDetail volunteerDetail = createVolunteerDetail(volunteerId); + + // when + VolunteerDetail savedDetail = volunteerDetailRepository.save(volunteerDetail); + + // then + assertThat(savedDetail).isNotNull(); + assertThat(savedDetail.getVolunteerId()).isEqualTo(volunteerId); + assertThat(savedDetail.getName()).isEqualTo(volunteerDetail.getName()); + } + + private VolunteerDetail createVolunteerDetail(UUID volunteerId) { + return VolunteerDetail.builder() + .volunteerId(volunteerId) + .name("making") + .email("making@example.com") + .gender(Gender.MALE) + .birthDate("1998-06-08") + .contactNumber("010-1234-5678") + .build(); + } +} \ No newline at end of file From 25d0cd34b9813ae600d541ab13a9882c620525b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 23:40:46 +0900 Subject: [PATCH 29/54] =?UTF-8?q?test(VolunteerQueryService):=20=EA=B8=B0?= =?UTF-8?q?=EA=B4=80=EC=9D=98=20=EB=B4=89=EC=82=AC=EC=9E=90=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A0=95=EB=B3=B4=20=EC=A1=B0=ED=9A=8C=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EA=B6=8C=ED=95=9C=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../somemore/volunteer/service/VolunteerQueryService.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java b/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java index 0fbd94e11..1bb761f10 100644 --- a/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java +++ b/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java @@ -1,6 +1,6 @@ package com.somemore.volunteer.service; -import com.somemore.facade.validator.VolunteerDetailAccessValidator; +import com.somemore.facade.validator.VolunteerDetailAccessValidatorImpl; import com.somemore.global.exception.BadRequestException; import com.somemore.volunteer.domain.Volunteer; import com.somemore.volunteer.domain.VolunteerDetail; @@ -25,7 +25,7 @@ public class VolunteerQueryService implements VolunteerQueryUseCase { private final VolunteerRepository volunteerRepository; private final VolunteerDetailRepository volunteerDetailRepository; - private final VolunteerDetailAccessValidator volunteerDetailAccessValidator; + private final VolunteerDetailAccessValidatorImpl volunteerDetailAccessValidatorImpl; @Override public VolunteerResponseDto getMyProfile(UUID volunteerId) { @@ -46,8 +46,7 @@ public VolunteerResponseDto getVolunteerProfile(UUID volunteerId) { @Override public VolunteerResponseDto getVolunteerDetailedProfile(UUID volunteerId, UUID centerId) { - // TODO 권한 검사 - + volunteerDetailAccessValidatorImpl.validateByCenterId(centerId, volunteerId); return VolunteerResponseDto.from( findVolunteer(volunteerId), From 5fac32aefa27fd49bef088604f22e93ff1749648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 23:41:25 +0900 Subject: [PATCH 30/54] =?UTF-8?q?test(VolunteerDetailAccessValidator):=20?= =?UTF-8?q?=EB=B4=89=EC=82=AC=EC=9E=90=20=EC=83=81=EC=84=B8=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=A5=BC=20=EA=B8=B0=EA=B4=80=EC=9D=B4=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=ED=95=98=EB=8A=94=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...olunteerDetailAccessValidatorImplTest.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/test/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImplTest.java diff --git a/src/test/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImplTest.java b/src/test/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImplTest.java new file mode 100644 index 000000000..d5031792e --- /dev/null +++ b/src/test/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImplTest.java @@ -0,0 +1,67 @@ +package com.somemore.facade.validator; + +import com.somemore.IntegrationTestSupport; +import com.somemore.global.exception.BadRequestException; +import com.somemore.recruitboard.domain.RecruitBoard; +import com.somemore.recruitboard.repository.RecruitBoardRepository; +import com.somemore.volunteerApply.domain.ApplyStatus; +import com.somemore.volunteerApply.domain.VolunteerApply; +import com.somemore.volunteerApply.repository.VolunteerApplyRepository; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +import java.util.UUID; + +import static com.somemore.common.fixture.RecruitBoardFixture.createRecruitBoard; +import static com.somemore.global.exception.ExceptionMessage.UNAUTHORIZED_VOLUNTEER_DETAIL; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@Transactional +class VolunteerDetailAccessValidatorImplTest extends IntegrationTestSupport { + + @Autowired + private VolunteerDetailAccessValidatorImpl volunteerDetailAccessValidatorImpl; + + @Autowired + private RecruitBoardRepository recruitBoardRepository; + + @Autowired + private VolunteerApplyRepository volunteerApplyRepository; + + @DisplayName("타겟 봉사자가 모집 글과 연관된 경우 검증 통과, 연관되지 않은 경우 예외를 던진다") + @Test + void validateByCenterIdThrowsExceptionWhenVolunteerNotLinked() { + // given + UUID centerId = UUID.randomUUID(); + + RecruitBoard recruitBoard = createRecruitBoard(centerId); + recruitBoardRepository.save(recruitBoard); + + UUID unrelatedVolunteerId = UUID.randomUUID(); + UUID relatedVolunteerId = UUID.randomUUID(); + + VolunteerApply volunteerApply = createVolunteerApply(recruitBoard.getId(), relatedVolunteerId); + volunteerApplyRepository.save(volunteerApply); + + // when + // then + assertThatCode(() -> volunteerDetailAccessValidatorImpl.validateByCenterId(centerId, relatedVolunteerId)) + .doesNotThrowAnyException(); + + assertThatThrownBy(() -> volunteerDetailAccessValidatorImpl.validateByCenterId(centerId, unrelatedVolunteerId)) + .isInstanceOf(BadRequestException.class) + .hasMessage(UNAUTHORIZED_VOLUNTEER_DETAIL.getMessage()); + } + + private VolunteerApply createVolunteerApply(Long recruitId, UUID volunteerId) { + return VolunteerApply.builder() + .recruitBoardId(recruitId) + .volunteerId(volunteerId) + .status(ApplyStatus.WAITING) + .attended(false) + .build(); + } +} \ No newline at end of file From b1da776ac6a1bd3d6c439dc244129b65750786ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Fri, 29 Nov 2024 23:42:52 +0900 Subject: [PATCH 31/54] =?UTF-8?q?test(VolunteerQueryService):=20=EB=B4=89?= =?UTF-8?q?=EC=82=AC=EC=9E=90=20=EA=B8=B0=EB=B3=B8/=EC=83=81=EC=84=B8=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=A1=B0=ED=9A=8C=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8,=20=EB=8B=89=EB=84=A4=EC=9E=84=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - beforeEach 를 transactional로 변경 --- .../service/VolunteerQueryServiceTest.java | 126 +++++++++++++++--- 1 file changed, 109 insertions(+), 17 deletions(-) diff --git a/src/test/java/com/somemore/volunteer/service/VolunteerQueryServiceTest.java b/src/test/java/com/somemore/volunteer/service/VolunteerQueryServiceTest.java index ec8454d77..25fc6cbdb 100644 --- a/src/test/java/com/somemore/volunteer/service/VolunteerQueryServiceTest.java +++ b/src/test/java/com/somemore/volunteer/service/VolunteerQueryServiceTest.java @@ -4,18 +4,25 @@ import com.somemore.auth.oauth.OAuthProvider; import com.somemore.global.exception.BadRequestException; import com.somemore.volunteer.domain.Volunteer; +import com.somemore.volunteer.domain.VolunteerDetail; +import com.somemore.volunteer.dto.request.VolunteerRegisterRequestDto; +import com.somemore.volunteer.dto.response.VolunteerResponseDto; +import com.somemore.volunteer.repository.VolunteerDetailRepository; import com.somemore.volunteer.repository.VolunteerRepository; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; import java.util.UUID; import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_VOLUNTEER; +import static com.somemore.global.exception.ExceptionMessage.UNAUTHORIZED_VOLUNTEER_DETAIL; +import static com.somemore.volunteer.domain.Volunteer.createDefault; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +@Transactional class VolunteerQueryServiceTest extends IntegrationTestSupport { @Autowired @@ -24,18 +31,18 @@ class VolunteerQueryServiceTest extends IntegrationTestSupport { @Autowired private VolunteerRepository volunteerRepository; - @AfterEach - void tearDown() { - volunteerRepository.deleteAllInBatch(); - } + @Autowired + private VolunteerDetailRepository volunteerDetailRepository; + + final String oAuthId = "example-oauth-id"; + final OAuthProvider oAuthProvider = OAuthProvider.NAVER; + @DisplayName("존재하는 OAuth ID로 봉사자 ID를 조회한다") @Test - void findVolunteerId() { + void getVolunteerIdByOAuthId() { // given - String oAuthId = "example-oauth-id"; - Volunteer volunteer = Volunteer.createDefault(OAuthProvider.NAVER, oAuthId); - + Volunteer volunteer = createDefault(oAuthProvider, oAuthId); volunteerRepository.save(volunteer); // when @@ -49,10 +56,7 @@ void findVolunteerId() { @DisplayName("존재하지 않는 OAuth ID로 조회 시 예외를 던진다") @Test - void throwExceptionWhenVolunteerNotFound() { - // given - String oAuthId = "non-existing-oauth-id"; - + void getVolunteerIdByNonExistOAuthId() { // when // then assertThatThrownBy(() -> volunteerQueryService.getVolunteerIdByOAuthId(oAuthId)) @@ -63,11 +67,8 @@ void throwExceptionWhenVolunteerNotFound() { @DisplayName("봉사자의 id로 nickname을 조회한다.") @Test void getNicknameById() { - //given - String oAuthId = "example-oauth-id"; - Volunteer volunteer = Volunteer.createDefault(OAuthProvider.NAVER, oAuthId); - + Volunteer volunteer = createDefault(oAuthProvider, oAuthId); volunteerRepository.save(volunteer); //when @@ -76,4 +77,95 @@ void getNicknameById() { //then assertThat(nickname).isEqualTo(volunteer.getNickname()); } + + @DisplayName("존재하지 않는 봉사자 ID로 닉네임 조회 시 예외를 던진다") + @Test + void throwExceptionWhenNicknameNotFound() { + // given + UUID volunteerId = UUID.randomUUID(); + + // when + // then + assertThatThrownBy(() -> volunteerQueryService.getNicknameById(volunteerId)) + .isInstanceOf(BadRequestException.class) + .hasMessage(NOT_EXISTS_VOLUNTEER.getMessage()); + } + + @DisplayName("내 프로필 조회 성공") + @Test + void getMyProfile() { + // given + Volunteer volunteer = createDefault(oAuthProvider, oAuthId); + volunteerRepository.save(volunteer); + UUID volunteerId = volunteer.getId(); + + VolunteerDetail volunteerDetail = createVolunteerDetail(volunteerId); + volunteerDetailRepository.save(volunteerDetail); + + // when + VolunteerResponseDto response = volunteerQueryService.getMyProfile(volunteerId); + + // then + assertThat(response).isNotNull(); + assertThat(response.volunteerId()).isEqualTo(volunteerId.toString()); + assertThat(response.nickname()).isEqualTo(volunteer.getNickname()); + } + + @DisplayName("봉사자 프로필 조회 성공") + @Test + void getVolunteerProfile() { + // given + Volunteer volunteer = createDefault(oAuthProvider, oAuthId); + volunteerRepository.save(volunteer); + UUID volunteerId = volunteer.getId(); + + VolunteerDetail volunteerDetail = createVolunteerDetail(volunteerId); + volunteerDetailRepository.save(volunteerDetail); + + // when + VolunteerResponseDto response = volunteerQueryService.getVolunteerProfile(volunteerId); + + // then + assertThat(response).isNotNull(); + assertThat(response.volunteerId()).isEqualTo(volunteerId.toString()); + assertThat(response.nickname()).isEqualTo(volunteer.getNickname()); + assertThat(response.volunteerDetailResponseDto()).isNull(); + } + + @DisplayName("권한이 없는 기관의 봉사자 상세 프로필 조회 실패") + @Test + void getVolunteerDetailedProfile() { + // given + UUID centerId = UUID.randomUUID(); + + Volunteer volunteer = createDefault(oAuthProvider, oAuthId); + volunteerRepository.save(volunteer); + UUID volunteerId = volunteer.getId(); + + VolunteerDetail volunteerDetail = createVolunteerDetail(volunteerId); + volunteerDetailRepository.save(volunteerDetail); + + // when + // then + assertThatThrownBy(() -> volunteerQueryService.getVolunteerDetailedProfile(volunteerId, centerId)) + .isInstanceOf(BadRequestException.class) + .hasMessage(UNAUTHORIZED_VOLUNTEER_DETAIL.getMessage()); + } + + private static VolunteerDetail createVolunteerDetail(UUID volunteerId) { + + VolunteerRegisterRequestDto volunteerRegisterRequestDto = + new VolunteerRegisterRequestDto( + OAuthProvider.NAVER, + "example-oauth-id", + "making", + "making@example.com", + "male", + "06-08", + "1998", + "010-1234-5678" + ); + + return VolunteerDetail.of(volunteerRegisterRequestDto, volunteerId); + } } From d2af443abccc7fc305090f09784e3668b213d1f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sat, 30 Nov 2024 00:20:20 +0900 Subject: [PATCH 32/54] =?UTF-8?q?feat(IntegrationTestSupport):=20@AutoConf?= =?UTF-8?q?igureMockMvc=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/com/somemore/IntegrationTestSupport.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/com/somemore/IntegrationTestSupport.java b/src/test/java/com/somemore/IntegrationTestSupport.java index cba699570..842b0d708 100644 --- a/src/test/java/com/somemore/IntegrationTestSupport.java +++ b/src/test/java/com/somemore/IntegrationTestSupport.java @@ -1,10 +1,12 @@ package com.somemore; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; @ActiveProfiles("test") @SpringBootTest +@AutoConfigureMockMvc public abstract class IntegrationTestSupport { } From a7c176c46f19bbfa09625beb90698846df039dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sat, 30 Nov 2024 00:20:27 +0900 Subject: [PATCH 33/54] =?UTF-8?q?test(VolunteerSignController):=20Controll?= =?UTF-8?q?erTestSupport=20=EC=83=81=EC=86=8D=EB=B0=9B=EB=8F=84=EB=A1=9D?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../volunteer/controller/VolunteerSignControllerTest.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/somemore/volunteer/controller/VolunteerSignControllerTest.java b/src/test/java/com/somemore/volunteer/controller/VolunteerSignControllerTest.java index 1af24e071..541f1d78c 100644 --- a/src/test/java/com/somemore/volunteer/controller/VolunteerSignControllerTest.java +++ b/src/test/java/com/somemore/volunteer/controller/VolunteerSignControllerTest.java @@ -1,11 +1,9 @@ package com.somemore.volunteer.controller; -import com.somemore.IntegrationTestSupport; +import com.somemore.ControllerTestSupport; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; -import org.springframework.boot.test.context.SpringBootTest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.web.servlet.MockMvc; @@ -13,9 +11,7 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -@SpringBootTest -@AutoConfigureMockMvc -class VolunteerSignControllerTest extends IntegrationTestSupport { +class VolunteerSignControllerTest extends ControllerTestSupport { @Autowired private MockMvc mockMvc; From 931a6fee37ca19d3788dcaa0b1f567f83d21b4f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sat, 30 Nov 2024 00:39:23 +0900 Subject: [PATCH 34/54] =?UTF-8?q?test(center):=20=EA=B3=B5=EB=B0=B1=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../center/controller/CenterQueryApiControllerTest.java | 2 +- .../service/RegisterInterestCenterServiceTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/somemore/center/controller/CenterQueryApiControllerTest.java b/src/test/java/com/somemore/center/controller/CenterQueryApiControllerTest.java index 904b231ea..55bd28c5d 100644 --- a/src/test/java/com/somemore/center/controller/CenterQueryApiControllerTest.java +++ b/src/test/java/com/somemore/center/controller/CenterQueryApiControllerTest.java @@ -84,7 +84,7 @@ void getCenterProfile_NotFound() throws Exception { .andDo(print()) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.status").value("400")) - .andExpect(jsonPath("$.detail").value("존재하지 않는 기관 입니다.")); + .andExpect(jsonPath("$.detail").value("존재하지 않는 기관입니다.")); verify(centerQueryUseCase, times(1)).getCenterProfileByCenterId(nonExistentCenterId); } diff --git a/src/test/java/com/somemore/interestcenter/service/RegisterInterestCenterServiceTest.java b/src/test/java/com/somemore/interestcenter/service/RegisterInterestCenterServiceTest.java index a7e7bbeee..4546f5dd7 100644 --- a/src/test/java/com/somemore/interestcenter/service/RegisterInterestCenterServiceTest.java +++ b/src/test/java/com/somemore/interestcenter/service/RegisterInterestCenterServiceTest.java @@ -87,7 +87,7 @@ void registerInterestCenter_WithInvalidCenterId_ShouldThrowException() { }); //then - assertEquals("존재하지 않는 기관 입니다.", exception.getMessage()); + assertEquals("존재하지 않는 기관입니다.", exception.getMessage()); } private Center createCenter() { From 81c23738afff9b17a47fe4e7322b362e9f8a307f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sat, 30 Nov 2024 00:39:52 +0900 Subject: [PATCH 35/54] =?UTF-8?q?test(VolunteerQueryController):=20?= =?UTF-8?q?=ED=83=80=EC=9D=B8=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VolunteerQueryControllerTest.java | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 src/test/java/com/somemore/volunteer/controller/VolunteerQueryControllerTest.java diff --git a/src/test/java/com/somemore/volunteer/controller/VolunteerQueryControllerTest.java b/src/test/java/com/somemore/volunteer/controller/VolunteerQueryControllerTest.java new file mode 100644 index 000000000..5dc318dda --- /dev/null +++ b/src/test/java/com/somemore/volunteer/controller/VolunteerQueryControllerTest.java @@ -0,0 +1,62 @@ +package com.somemore.volunteer.controller; + +import com.somemore.ControllerTestSupport; +import com.somemore.volunteer.dto.response.VolunteerResponseDto; +import com.somemore.volunteer.usecase.VolunteerQueryUseCase; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.UUID; + +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +class VolunteerQueryControllerTest extends ControllerTestSupport { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private VolunteerQueryUseCase volunteerQueryUseCase; + + @Test + @DisplayName("타인의 프로필을 조회할 수 있다.") + void getVolunteerProfile() throws Exception { + // given + UUID volunteerId = UUID.randomUUID(); + VolunteerResponseDto responseDto = createMockVolunteerResponse(); + + given(volunteerQueryUseCase.getVolunteerProfile(volunteerId)).willReturn(responseDto); + + // when & then + mockMvc.perform(get("/profile/{volunteerId}", volunteerId) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.code").value(200)) + .andExpect(jsonPath("$.data").exists()) + .andExpect(jsonPath("$.message").value("프로필 조회 성공")); + + verify(volunteerQueryUseCase, times(1)).getVolunteerProfile(volunteerId); + } + + private VolunteerResponseDto createMockVolunteerResponse() { + return new VolunteerResponseDto( + UUID.randomUUID().toString(), + "Test", + "http://example.com/image.jpg", + "Ima volunteer!", + "Red", + 100, + 10, + null + ); + } +} \ No newline at end of file From 37e7922455b83028e5e65d1b9da7bbb94c9391db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sat, 30 Nov 2024 23:36:06 +0900 Subject: [PATCH 36/54] =?UTF-8?q?test(ControllerTestSupport):=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=20OFF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/java/com/somemore/ControllerTestSupport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/somemore/ControllerTestSupport.java b/src/test/java/com/somemore/ControllerTestSupport.java index 27537fc4a..832bad10c 100644 --- a/src/test/java/com/somemore/ControllerTestSupport.java +++ b/src/test/java/com/somemore/ControllerTestSupport.java @@ -10,7 +10,7 @@ @ActiveProfiles("test") @SpringBootTest -@AutoConfigureMockMvc +@AutoConfigureMockMvc(addFilters = false) public abstract class ControllerTestSupport { @Autowired From 8689d3801d2f91ef9a02ccb01c96b6802beedee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sat, 30 Nov 2024 23:41:12 +0900 Subject: [PATCH 37/54] =?UTF-8?q?test(VolunteerController):=20=EC=BB=A8?= =?UTF-8?q?=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VolunteerQueryControllerTest.java | 62 ------------------- .../VolunteerSignControllerTest.java | 62 ------------------- 2 files changed, 124 deletions(-) delete mode 100644 src/test/java/com/somemore/volunteer/controller/VolunteerQueryControllerTest.java delete mode 100644 src/test/java/com/somemore/volunteer/controller/VolunteerSignControllerTest.java diff --git a/src/test/java/com/somemore/volunteer/controller/VolunteerQueryControllerTest.java b/src/test/java/com/somemore/volunteer/controller/VolunteerQueryControllerTest.java deleted file mode 100644 index 5dc318dda..000000000 --- a/src/test/java/com/somemore/volunteer/controller/VolunteerQueryControllerTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.somemore.volunteer.controller; - -import com.somemore.ControllerTestSupport; -import com.somemore.volunteer.dto.response.VolunteerResponseDto; -import com.somemore.volunteer.usecase.VolunteerQueryUseCase; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; - -import java.util.UUID; - -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -class VolunteerQueryControllerTest extends ControllerTestSupport { - - @Autowired - private MockMvc mockMvc; - - @MockBean - private VolunteerQueryUseCase volunteerQueryUseCase; - - @Test - @DisplayName("타인의 프로필을 조회할 수 있다.") - void getVolunteerProfile() throws Exception { - // given - UUID volunteerId = UUID.randomUUID(); - VolunteerResponseDto responseDto = createMockVolunteerResponse(); - - given(volunteerQueryUseCase.getVolunteerProfile(volunteerId)).willReturn(responseDto); - - // when & then - mockMvc.perform(get("/profile/{volunteerId}", volunteerId) - .accept(MediaType.APPLICATION_JSON)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.code").value(200)) - .andExpect(jsonPath("$.data").exists()) - .andExpect(jsonPath("$.message").value("프로필 조회 성공")); - - verify(volunteerQueryUseCase, times(1)).getVolunteerProfile(volunteerId); - } - - private VolunteerResponseDto createMockVolunteerResponse() { - return new VolunteerResponseDto( - UUID.randomUUID().toString(), - "Test", - "http://example.com/image.jpg", - "Ima volunteer!", - "Red", - 100, - 10, - null - ); - } -} \ No newline at end of file diff --git a/src/test/java/com/somemore/volunteer/controller/VolunteerSignControllerTest.java b/src/test/java/com/somemore/volunteer/controller/VolunteerSignControllerTest.java deleted file mode 100644 index 541f1d78c..000000000 --- a/src/test/java/com/somemore/volunteer/controller/VolunteerSignControllerTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.somemore.volunteer.controller; - -import com.somemore.ControllerTestSupport; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.mock.web.MockHttpServletResponse; -import org.springframework.test.web.servlet.MockMvc; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -class VolunteerSignControllerTest extends ControllerTestSupport { - - @Autowired - private MockMvc mockMvc; - - @Test - @DisplayName("유효한 OAuth 제공자로 로그인 URL을 생성한다.") - void signInWithValidProvider() throws Exception { - // Given - String oauthProvider = "naver"; - - // When - // Then - mockMvc.perform(post("/api/volunteer/sign-in/oauth/{oauthProvider}", oauthProvider)) - .andExpect(status().is3xxRedirection()) - .andExpect(result -> { - MockHttpServletResponse response = result.getResponse(); - String redirectedUrl = response.getRedirectedUrl(); - assertThat(redirectedUrl).isNotNull(); - assertThat(redirectedUrl).contains("oauth2/authorization/naver"); - }); - } - - @Test - @DisplayName("지원되지 않는 OAuth 제공자로 로그인 시 400 에러를 반환한다.") - void signInWithInvalidProvider() throws Exception { - // Given - String invalidProvider = "unsupported-provider"; - - // When - // Then - mockMvc.perform(post("/api/volunteer/sign-in/oauth/{oauthProvider}", invalidProvider)) - .andExpect(status().isBadRequest()); - } - - @Test - @DisplayName("로그아웃 요청 시 성공 메시지를 반환한다.") - void signOut() throws Exception { - // When - // Then - mockMvc.perform(post("/api/volunteer/sign-out")) - .andExpect(status().isOk()) - .andExpect(result -> { - MockHttpServletResponse response = result.getResponse(); - String responseBody = response.getContentAsString(); - assertThat(responseBody).contains("로그아웃되었습니다"); - }); - } -} \ No newline at end of file From c1370be22e8b6adfc0b0185263a0b1ac190a1a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sat, 30 Nov 2024 23:42:20 +0900 Subject: [PATCH 38/54] =?UTF-8?q?feat(VolunteerQueryController):=20@Secure?= =?UTF-8?q?d=20=EC=A0=81=EC=9A=A9,=20Mapping=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/VolunteerQueryController.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/somemore/volunteer/controller/VolunteerQueryController.java b/src/main/java/com/somemore/volunteer/controller/VolunteerQueryController.java index 47787d9c9..950e8f505 100644 --- a/src/main/java/com/somemore/volunteer/controller/VolunteerQueryController.java +++ b/src/main/java/com/somemore/volunteer/controller/VolunteerQueryController.java @@ -7,9 +7,11 @@ import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.annotation.Secured; import org.springframework.security.core.annotation.AuthenticationPrincipal; 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 java.util.UUID; @@ -17,13 +19,15 @@ @RestController @Slf4j @RequiredArgsConstructor -@Tag(name = "Find Volunteer", description = "Find Volunteer") +@RequestMapping("/api/profile") +@Tag(name = "GET Volunteer", description = "봉사자 조회") public class VolunteerQueryController { private final VolunteerQueryUseCase volunteerQueryUseCase; - @GetMapping("/profile/me") @Operation(summary = "본인 상세 프로필 조회", description = "현재 로그인된 사용자의 상세 프로필을 조회합니다.") + @Secured("ROLE_VOLUNTEER") + @GetMapping("/me") public ApiResponse getMyProfile( @AuthenticationPrincipal String volunteerId) { @@ -33,7 +37,7 @@ public ApiResponse getMyProfile( "프로필 조회 성공"); } - @GetMapping("/profile/{volunteerId}") + @GetMapping("/{volunteerId}") @Operation(summary = "타인 프로필 조회", description = "특정 봉사자의 프로필을 조회합니다. 상세 정보는 포함되지 않습니다.") public ApiResponse getVolunteerProfile( @PathVariable UUID volunteerId) { @@ -45,7 +49,8 @@ public ApiResponse getVolunteerProfile( ); } - @GetMapping("/profile/{volunteerId}/detailed") + @GetMapping("/{volunteerId}/detailed") + @Secured("ROLE_CENTER") @Operation(summary = "타인 상세 프로필 조회", description = "기관이 작성한 모집 글에 지원한 봉사자의 상세 프로필을 조회합니다.") public ApiResponse getVolunteerDetailedProfile( @PathVariable UUID volunteerId, From b653e3857a6b8f436d293502ff062c329e97e5b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sat, 30 Nov 2024 23:43:10 +0900 Subject: [PATCH 39/54] =?UTF-8?q?feat(UserRole):=20GrantedAuthority=20?= =?UTF-8?q?=EC=83=81=EC=86=8D,=20authority=20=ED=95=84=EB=93=9C,=20?= =?UTF-8?q?=EC=A0=95=EC=A0=81=20=EB=A9=94=EC=84=9C=EB=93=9C=20from=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../somemore/auth/jwt/domain/UserRole.java | 31 ++++++++++++++++--- .../somemore/auth/jwt/filter/UserRole.java | 7 ----- 2 files changed, 27 insertions(+), 11 deletions(-) delete mode 100644 src/main/java/com/somemore/auth/jwt/filter/UserRole.java diff --git a/src/main/java/com/somemore/auth/jwt/domain/UserRole.java b/src/main/java/com/somemore/auth/jwt/domain/UserRole.java index 163b9ce13..6bc917e0e 100644 --- a/src/main/java/com/somemore/auth/jwt/domain/UserRole.java +++ b/src/main/java/com/somemore/auth/jwt/domain/UserRole.java @@ -1,7 +1,30 @@ package com.somemore.auth.jwt.domain; -public enum UserRole { - VOLUNTEER, - CENTER, - ADMIN +import com.somemore.auth.jwt.exception.JwtException; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.GrantedAuthority; + +import static com.somemore.auth.jwt.exception.JwtErrorType.UNKNOWN_ERROR; + +@RequiredArgsConstructor +public enum UserRole implements GrantedAuthority { + VOLUNTEER("ROLE_VOLUNTEER"), + CENTER("ROLE_CENTER"), + ADMIN("ROLE_ADMIN"); + + private final String authority; + + @Override + public String getAuthority() { + return this.authority; + } + + public static UserRole from(String role) { + for (UserRole userRole : values()) { + if (userRole.name().equals(role)) { + return userRole; + } + } + throw new JwtException(UNKNOWN_ERROR); + } } diff --git a/src/main/java/com/somemore/auth/jwt/filter/UserRole.java b/src/main/java/com/somemore/auth/jwt/filter/UserRole.java deleted file mode 100644 index 857ee5c8a..000000000 --- a/src/main/java/com/somemore/auth/jwt/filter/UserRole.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.somemore.auth.jwt.filter; - -public enum UserRole { - VOLUNTEER, - CENTER, - ADMIN -} From cb637fa00481233c14c0e0a365831314c7ed751c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sat, 30 Nov 2024 23:45:11 +0900 Subject: [PATCH 40/54] =?UTF-8?q?feat(UserRole):=20UserRole.name()=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=97=90=EC=84=9C=20=EB=AA=85=EC=8B=9C?= =?UTF-8?q?=EC=A0=81=EC=9D=B8=20Authority=20=ED=95=84=EB=93=9C=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=20=EB=A9=94=EC=84=9C=EB=93=9C=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jwt/service/GenerateTokensOnLoginService.java | 2 +- .../somemore/auth/jwt/service/JwtServiceTest.java | 15 +++++++-------- .../service/SignOutVolunteerServiceTest.java | 8 ++++---- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/somemore/auth/jwt/service/GenerateTokensOnLoginService.java b/src/main/java/com/somemore/auth/jwt/service/GenerateTokensOnLoginService.java index a0cd82ee3..06ddcc966 100644 --- a/src/main/java/com/somemore/auth/jwt/service/GenerateTokensOnLoginService.java +++ b/src/main/java/com/somemore/auth/jwt/service/GenerateTokensOnLoginService.java @@ -35,7 +35,7 @@ public EncodedToken saveRefreshTokenAndReturnAccessToken(UUID volunteerId) { private EncodedToken generateToken(UUID volunteerId, TokenType tokenType) { return jwtGenerator.generateToken( volunteerId.toString(), - UserRole.VOLUNTEER.name(), + UserRole.VOLUNTEER.getAuthority(), tokenType); } diff --git a/src/test/java/com/somemore/auth/jwt/service/JwtServiceTest.java b/src/test/java/com/somemore/auth/jwt/service/JwtServiceTest.java index 0519bcd3a..04119a8d6 100644 --- a/src/test/java/com/somemore/auth/jwt/service/JwtServiceTest.java +++ b/src/test/java/com/somemore/auth/jwt/service/JwtServiceTest.java @@ -39,7 +39,6 @@ class JwtServiceTest extends IntegrationTestSupport { @Autowired private RedisTemplate redisTemplate; - @AfterEach void tearDown() { redisTemplate.keys("*") @@ -55,12 +54,12 @@ void generateAndValidateToken() { TokenType tokenType = TokenType.ACCESS; // when - EncodedToken token = jwtService.generateToken(userId, role.name(), tokenType); + EncodedToken token = jwtService.generateToken(userId, role.getAuthority(), tokenType); // then Claims claims = jwtService.getClaims(token); assertThat(claims.get("id", String.class)).isEqualTo(userId); - assertThat(claims.get("role", String.class)).isEqualTo(role.name()); + assertThat(claims.get("role", String.class)).isEqualTo(role.getAuthority()); assertThat(claims.getExpiration()).isNotNull(); } @@ -72,8 +71,8 @@ void tokenExpirationPeriodIsExact() { UserRole role = UserRole.VOLUNTEER; // when - EncodedToken accessToken = jwtService.generateToken(userId, role.name(), TokenType.ACCESS); - EncodedToken refreshToken = jwtService.generateToken(userId, role.name(), TokenType.REFRESH); + EncodedToken accessToken = jwtService.generateToken(userId, role.getAuthority(), TokenType.ACCESS); + EncodedToken refreshToken = jwtService.generateToken(userId, role.getAuthority(), TokenType.REFRESH); // then Claims accessClaims = jwtService.getClaims(accessToken); @@ -94,8 +93,8 @@ void multipleTokensForSameUserAreDifferent() { UserRole role = UserRole.VOLUNTEER; // when - EncodedToken token1 = jwtService.generateToken(userId, role.name(), TokenType.ACCESS); - EncodedToken token2 = jwtService.generateToken(userId, role.name(), TokenType.ACCESS); + EncodedToken token1 = jwtService.generateToken(userId, role.getAuthority(), TokenType.ACCESS); + EncodedToken token2 = jwtService.generateToken(userId, role.getAuthority(), TokenType.ACCESS); // then assertThat(token1.value()).isNotEqualTo(token2.value()); @@ -189,7 +188,7 @@ void refreshTokenIsUpdated() { EncodedToken expiredAccessToken = createExpiredToken(userId, role); RefreshToken oldRefreshToken = createAndSaveRefreshToken(userId, expiredAccessToken, Instant.now().plusMillis(TokenType.REFRESH.getPeriod())); - EncodedToken newAccessToken = jwtService.generateToken(userId, role.name(), TokenType.ACCESS); + EncodedToken newAccessToken = jwtService.generateToken(userId, role.getAuthority(), TokenType.ACCESS); RefreshToken newRefreshToken = createAndSaveRefreshToken(userId, newAccessToken, Instant.now().plusMillis(TokenType.REFRESH.getPeriod())); // when diff --git a/src/test/java/com/somemore/volunteer/service/SignOutVolunteerServiceTest.java b/src/test/java/com/somemore/volunteer/service/SignOutVolunteerServiceTest.java index c6c9efd15..e88c6b5cc 100644 --- a/src/test/java/com/somemore/volunteer/service/SignOutVolunteerServiceTest.java +++ b/src/test/java/com/somemore/volunteer/service/SignOutVolunteerServiceTest.java @@ -4,9 +4,9 @@ import com.somemore.auth.cookie.CookieUseCase; import com.somemore.auth.jwt.domain.EncodedToken; import com.somemore.auth.jwt.domain.TokenType; +import com.somemore.auth.jwt.domain.UserRole; import com.somemore.auth.jwt.exception.JwtErrorType; import com.somemore.auth.jwt.exception.JwtException; -import com.somemore.auth.jwt.filter.UserRole; import com.somemore.auth.jwt.generator.JwtGenerator; import com.somemore.auth.jwt.refresh.domain.RefreshToken; import com.somemore.auth.jwt.refresh.manager.RefreshTokenManager; @@ -57,12 +57,12 @@ void tearDown() { @DisplayName("로그아웃 시 액세스 토큰 쿠키를 삭제하고 리프레시 토큰을 제거해야 한다.") void signOutDeletesTokens() { // Given - EncodedToken accessToken = jwtGenerator.generateToken(volunteerId, role.name(), TokenType.ACCESS); + EncodedToken accessToken = jwtGenerator.generateToken(volunteerId, role.getAuthority(), TokenType.ACCESS); RefreshToken refreshToken = new RefreshToken( volunteerId, accessToken, - jwtGenerator.generateToken(volunteerId, role.name(), TokenType.REFRESH)); + jwtGenerator.generateToken(volunteerId, role.getAuthority(), TokenType.REFRESH)); refreshTokenManager.save(refreshToken); cookieUseCase.setAccessToken(response, accessToken.value()); @@ -88,4 +88,4 @@ void signOutWithoutRefreshToken() { assertThatNoException().isThrownBy(() -> signOutVolunteerService.signOut(response, volunteerId)); assertThat(Arrays.toString(response.getCookies())).contains(TokenType.SIGNOUT.name()); } -} \ No newline at end of file +} From 20b4fb33eca68319f8a64826be96f5825ac850ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sat, 30 Nov 2024 23:46:08 +0900 Subject: [PATCH 41/54] =?UTF-8?q?feat(CookieService):=20=ED=86=A0=ED=81=B0?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/somemore/auth/cookie/CookieService.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/somemore/auth/cookie/CookieService.java b/src/main/java/com/somemore/auth/cookie/CookieService.java index f68080cca..c81bee658 100644 --- a/src/main/java/com/somemore/auth/cookie/CookieService.java +++ b/src/main/java/com/somemore/auth/cookie/CookieService.java @@ -16,12 +16,14 @@ public class CookieService implements CookieUseCase { public void setAccessToken(HttpServletResponse response, String value) { ResponseCookie cookie = generateCookie(TokenType.ACCESS, value); response.addHeader("Set-Cookie", cookie.toString()); + log.info("SET_COOKIE_ACCESS_TOKEN = {}", value); } @Override public void deleteAccessToken(HttpServletResponse response) { ResponseCookie cookie = generateCookie(TokenType.SIGNOUT, TokenType.SIGNOUT.name()); response.addHeader("Set-Cookie", cookie.toString()); + log.info("DELETE_COOKIE_ACCESS_TOKEN"); } private static ResponseCookie generateCookie(TokenType tokenType, String value) { From fb54ab32c2ad1c8eeac927119dcc7b61ef27b9d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sat, 30 Nov 2024 23:47:45 +0900 Subject: [PATCH 42/54] =?UTF-8?q?feat(DevAccountSetUpConfig):=20repository?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD,=20.name()=EC=9D=84=20.getAuthority?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/somemore/auth/util/DevAccountSetUpConfig.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/somemore/auth/util/DevAccountSetUpConfig.java b/src/main/java/com/somemore/auth/util/DevAccountSetUpConfig.java index 42e98fb60..f7e9d14b4 100644 --- a/src/main/java/com/somemore/auth/util/DevAccountSetUpConfig.java +++ b/src/main/java/com/somemore/auth/util/DevAccountSetUpConfig.java @@ -11,7 +11,7 @@ import com.somemore.center.domain.Center; import com.somemore.center.repository.CenterJpaRepository; import com.somemore.volunteer.domain.Volunteer; -import com.somemore.volunteer.repository.VolunteerJpaRepository; +import com.somemore.volunteer.repository.VolunteerRepository; import jakarta.annotation.PostConstruct; import jakarta.annotation.PreDestroy; import java.util.UUID; @@ -25,7 +25,7 @@ @Component public class DevAccountSetUpConfig { - private final VolunteerJpaRepository volunteerRepository; + private final VolunteerRepository volunteerRepository; private final CenterJpaRepository centerRepository; private final JwtGenerator jwtGenerator; private final RefreshTokenManager refreshTokenManager; @@ -88,7 +88,7 @@ private EncodedToken saveRefreshTokenAndReturnAccessToken(UUID id, UserRole role } private EncodedToken generateToken(UUID id, UserRole role, TokenType tokenType) { - return jwtGenerator.generateToken(id.toString(), role.name(), tokenType); + return jwtGenerator.generateToken(id.toString(), role.getAuthority(), tokenType); } private RefreshToken generateRefreshToken(UUID id, UserRole role, EncodedToken accessToken) { From 339de3ec8aa311a60fddd64e3e461e5ebd0e5b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sat, 30 Nov 2024 23:48:23 +0900 Subject: [PATCH 43/54] =?UTF-8?q?feat(HmacJwtGenerator):=20=EC=9D=BC?= =?UTF-8?q?=EA=B4=80=EC=84=B1=20=EC=9E=88=EB=8A=94=20=EC=83=81=EC=88=98=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/somemore/auth/jwt/generator/HmacJwtGenerator.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/somemore/auth/jwt/generator/HmacJwtGenerator.java b/src/main/java/com/somemore/auth/jwt/generator/HmacJwtGenerator.java index 1d25e5bca..26f686c79 100644 --- a/src/main/java/com/somemore/auth/jwt/generator/HmacJwtGenerator.java +++ b/src/main/java/com/somemore/auth/jwt/generator/HmacJwtGenerator.java @@ -36,12 +36,10 @@ public EncodedToken generateToken(String userId, String role, TokenType tokenTyp } private static Claims buildClaims(String userId, String role) { - final String ID = "id"; - final String ROLE = "role"; return Jwts.claims() - .add(ID, userId) - .add(ROLE, role) + .add("id", userId) + .add("role", role) .build(); } } From e79d56b06b2dc83398e26cd5027dbdd26ef6b61f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sat, 30 Nov 2024 23:59:37 +0900 Subject: [PATCH 44/54] =?UTF-8?q?refactor(JwtAuthFilter):=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81,=20name()=20=EC=82=AC=EC=9A=A9=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/jwt/filter/JwtAuthFilter.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/somemore/auth/jwt/filter/JwtAuthFilter.java b/src/main/java/com/somemore/auth/jwt/filter/JwtAuthFilter.java index 071cf7677..b21c94a0e 100644 --- a/src/main/java/com/somemore/auth/jwt/filter/JwtAuthFilter.java +++ b/src/main/java/com/somemore/auth/jwt/filter/JwtAuthFilter.java @@ -9,8 +9,6 @@ import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.core.Authentication; @@ -19,6 +17,9 @@ import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; +import java.io.IOException; +import java.util.List; + @RequiredArgsConstructor @Slf4j @Component @@ -34,7 +35,7 @@ protected boolean shouldNotFilter(HttpServletRequest request) { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, - FilterChain filterChain) throws ServletException, IOException { + FilterChain filterChain) throws ServletException, IOException { EncodedToken accessToken = getAccessToken(request); jwtUseCase.processAccessToken(accessToken, response); @@ -47,24 +48,24 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse private EncodedToken getAccessToken(HttpServletRequest request) { String accessToken = request.getHeader("Authorization"); - if (!accessToken.startsWith("Bearer ")) { - throw new JwtException(JwtErrorType.MISSING_TOKEN); - } - accessToken = accessToken.substring(7); + String tokenPrefix = "Bearer "; + if (accessToken.startsWith(tokenPrefix)) { + return new EncodedToken(accessToken.substring(tokenPrefix.length())); + } - return new EncodedToken(accessToken); + throw new JwtException(JwtErrorType.MISSING_TOKEN); } private JwtAuthenticationToken createAuthenticationToken(Claims claims, - EncodedToken accessToken) { + EncodedToken accessToken) { String userId = claims.get("id", String.class); - UserRole role = UserRole.valueOf(claims.get("role", String.class)); + String role = claims.get("role", String.class); return new JwtAuthenticationToken( userId, accessToken, - List.of(new SimpleGrantedAuthority(role.name())) + List.of(new SimpleGrantedAuthority(role)) ); } } From fd3c5abf4c7d493ae9f6eeac4cf42989bfa550f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sun, 1 Dec 2024 00:00:37 +0900 Subject: [PATCH 45/54] =?UTF-8?q?feat(SecurityConfig):=20@Slf4j,=20(secure?= =?UTF-8?q?dEnabled=20=3D=20true)=20=EC=B6=94=EA=B0=80=EB=A1=9C=20@Secured?= =?UTF-8?q?=20=EC=9E=91=EB=8F=99=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/somemore/global/configure/SecurityConfig.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/somemore/global/configure/SecurityConfig.java b/src/main/java/com/somemore/global/configure/SecurityConfig.java index 5951294ed..45a7e1527 100644 --- a/src/main/java/com/somemore/global/configure/SecurityConfig.java +++ b/src/main/java/com/somemore/global/configure/SecurityConfig.java @@ -6,7 +6,6 @@ import com.somemore.auth.oauth.handler.success.CustomOAuthSuccessHandler; import com.somemore.auth.oauth.service.CustomOAuth2UserService; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; @@ -20,8 +19,7 @@ @RequiredArgsConstructor @Configuration @EnableWebSecurity -@EnableMethodSecurity -@Slf4j +@EnableMethodSecurity(securedEnabled = true) public class SecurityConfig { private final CustomOAuth2UserService customOAuth2UserService; From d3f37a4203bac272649f3465cf049fae65137259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sun, 1 Dec 2024 00:06:14 +0900 Subject: [PATCH 46/54] =?UTF-8?q?cicd(jacoco):=20controller=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=EB=A5=BC=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BB=A4=EB=B2=84=EB=A6=AC=EC=A7=80=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=A0=9C=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 나는 컨트롤러 테스트가 밉다. --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index 5ba7f9aaa..494c337f5 100644 --- a/build.gradle +++ b/build.gradle @@ -116,6 +116,8 @@ def jacocoExcludePatterns = [ '**/domain/*', '**/domains/*', '**/fixture/*', + '**/controller/**', + '**/fixture/*', '**/*Factory*' ] @@ -132,6 +134,8 @@ def jacocoExcludePatternsForVerify = [ '*.domain.*', '*.domains.*', '*.fixture.*', + '*.controller.*', + '*.fixture.*', '*.*Factory*' ] From 70363678d8ada6312e7c35ed545a02fd210cd515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sun, 1 Dec 2024 00:19:12 +0900 Subject: [PATCH 47/54] =?UTF-8?q?refactor(VolunteerDetailAccessValidator):?= =?UTF-8?q?=20elseThrow=20=EB=B0=98=ED=99=98=EC=9D=B4=20=EC=97=86=EB=8A=94?= =?UTF-8?q?=20=EA=B2=83=EC=9D=84=20anyMatch=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../VolunteerDetailAccessValidatorImpl.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImpl.java b/src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImpl.java index 218d598ec..681d67fbc 100644 --- a/src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImpl.java +++ b/src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImpl.java @@ -23,13 +23,15 @@ public class VolunteerDetailAccessValidatorImpl implements VolunteerDetailAccess * 해당 모집글들에 연관된 봉사자들의 ID 목록에 타겟 봉사자 ID가 포함되어 있는지 검증. */ public void validateByCenterId(UUID centerId, UUID targetVolunteerId) { - List allNotCompletedIdsByCenterId = recruitBoardQueryUseCase.getNotCompletedIdsByCenterIds(centerId); + List notCompletedIdsByCenterIds = recruitBoardQueryUseCase.getNotCompletedIdsByCenterIds(centerId); - List volunteerIdsByRecruitIds = volunteerApplyQueryUseCase.getVolunteerIdsByRecruitIds(allNotCompletedIdsByCenterId); + List volunteerIdsByRecruitIds = volunteerApplyQueryUseCase.getVolunteerIdsByRecruitIds(notCompletedIdsByCenterIds); - volunteerIdsByRecruitIds.stream() - .filter(volunteerId -> volunteerId.equals(targetVolunteerId)) - .findAny() - .orElseThrow(() -> new BadRequestException(UNAUTHORIZED_VOLUNTEER_DETAIL)); + if (volunteerIdsByRecruitIds.stream() + .anyMatch(volunteerId -> volunteerId.equals(targetVolunteerId))) { + return; + } + + throw new BadRequestException(UNAUTHORIZED_VOLUNTEER_DETAIL); } } \ No newline at end of file From daac8ef04e1e96d9dda0f59c0653a39fd59d3ef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sun, 1 Dec 2024 00:32:16 +0900 Subject: [PATCH 48/54] =?UTF-8?q?feat(VolunteerQueryController):=20?= =?UTF-8?q?=EC=84=B1=EA=B3=B5=20=EB=A9=94=EC=8B=9C=EC=A7=80=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../volunteer/controller/VolunteerQueryController.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/somemore/volunteer/controller/VolunteerQueryController.java b/src/main/java/com/somemore/volunteer/controller/VolunteerQueryController.java index 950e8f505..3f9a1043a 100644 --- a/src/main/java/com/somemore/volunteer/controller/VolunteerQueryController.java +++ b/src/main/java/com/somemore/volunteer/controller/VolunteerQueryController.java @@ -34,7 +34,7 @@ public ApiResponse getMyProfile( return ApiResponse.ok( 200, volunteerQueryUseCase.getMyProfile(UUID.fromString(volunteerId)), - "프로필 조회 성공"); + "본인 상세 프로필 조회 성공"); } @GetMapping("/{volunteerId}") @@ -45,13 +45,13 @@ public ApiResponse getVolunteerProfile( return ApiResponse.ok( 200, volunteerQueryUseCase.getVolunteerProfile(volunteerId), - "프로필 조회 성공" + "타인 프로필 조회 성공" ); } @GetMapping("/{volunteerId}/detailed") @Secured("ROLE_CENTER") - @Operation(summary = "타인 상세 프로필 조회", description = "기관이 작성한 모집 글에 지원한 봉사자의 상세 프로필을 조회합니다.") + @Operation(summary = "지원자 상세 프로필 조회", description = "기관이 작성한 모집 글에 지원한 봉사자의 상세 프로필을 조회합니다.") public ApiResponse getVolunteerDetailedProfile( @PathVariable UUID volunteerId, @AuthenticationPrincipal String centerId) { @@ -59,7 +59,7 @@ public ApiResponse getVolunteerDetailedProfile( return ApiResponse.ok( 200, volunteerQueryUseCase.getVolunteerDetailedProfile(volunteerId, UUID.fromString(centerId)), - "프로필 조회 성공" + "지원자 상세 프로필 조회 성공" ); } } From be87e25f5e94f97cbabffe83bc53c40e74dcd007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sun, 1 Dec 2024 00:33:39 +0900 Subject: [PATCH 49/54] =?UTF-8?q?refactor(sonar=20=EB=B0=98=EC=98=81):=20u?= =?UTF-8?q?nused=20import,=20chaining=20join,=20=EB=AA=85=EC=8B=9C?= =?UTF-8?q?=EC=A0=81=EC=9D=B8=20=EC=97=94=ED=8B=B0=ED=8B=B0=20default=20fi?= =?UTF-8?q?elds?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/VolunteerDetailRepositoryImpl.java | 2 +- .../volunteer/repository/VolunteerJpaRepository.java | 3 --- .../volunteer/repository/VolunteerRepositoryImpl.java | 3 +-- .../volunteer/service/RegisterVolunteerService.java | 1 - .../somemore/volunteerApply/domain/VolunteerApply.java | 8 ++++---- .../repository/VolunteerApplyRepositoryImpl.java | 2 +- .../repository/RecruitBoardRepositoryImplTest.java | 4 +--- 7 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImpl.java b/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImpl.java index 2bdf71c2e..bdcb4476a 100644 --- a/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImpl.java +++ b/src/main/java/com/somemore/volunteer/repository/VolunteerDetailRepositoryImpl.java @@ -17,7 +17,7 @@ public class VolunteerDetailRepositoryImpl implements VolunteerDetailRepository private final VolunteerDetailJpaRepository volunteerDetailJpaRepository; private final JPAQueryFactory queryFactory; - private final QVolunteerDetail volunteerDetail = QVolunteerDetail.volunteerDetail; + private static final QVolunteerDetail volunteerDetail = QVolunteerDetail.volunteerDetail; @Override public VolunteerDetail save(VolunteerDetail volunteerDetail) { diff --git a/src/main/java/com/somemore/volunteer/repository/VolunteerJpaRepository.java b/src/main/java/com/somemore/volunteer/repository/VolunteerJpaRepository.java index 362a63daa..be4afdb52 100644 --- a/src/main/java/com/somemore/volunteer/repository/VolunteerJpaRepository.java +++ b/src/main/java/com/somemore/volunteer/repository/VolunteerJpaRepository.java @@ -3,8 +3,5 @@ import com.somemore.volunteer.domain.Volunteer; import org.springframework.data.jpa.repository.JpaRepository; -import java.util.Optional; -import java.util.UUID; - public interface VolunteerJpaRepository extends JpaRepository { } diff --git a/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java b/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java index 87a6ef8f6..fcda52d4a 100644 --- a/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java +++ b/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java @@ -10,7 +10,6 @@ import java.util.Optional; import java.util.UUID; -import java.util.function.Function; @RequiredArgsConstructor @Repository @@ -19,7 +18,7 @@ public class VolunteerRepositoryImpl implements VolunteerRepository { private final VolunteerJpaRepository volunteerJpaRepository; private final JPAQueryFactory queryFactory; - private final QVolunteer volunteer = QVolunteer.volunteer; + private static final QVolunteer volunteer = QVolunteer.volunteer; @Override public Volunteer save(Volunteer volunteer) { diff --git a/src/main/java/com/somemore/volunteer/service/RegisterVolunteerService.java b/src/main/java/com/somemore/volunteer/service/RegisterVolunteerService.java index e27a8c077..8feb930c1 100644 --- a/src/main/java/com/somemore/volunteer/service/RegisterVolunteerService.java +++ b/src/main/java/com/somemore/volunteer/service/RegisterVolunteerService.java @@ -3,7 +3,6 @@ import com.somemore.volunteer.domain.Volunteer; import com.somemore.volunteer.domain.VolunteerDetail; import com.somemore.volunteer.dto.request.VolunteerRegisterRequestDto; -import com.somemore.volunteer.repository.VolunteerDetailJpaRepository; import com.somemore.volunteer.repository.VolunteerDetailRepository; import com.somemore.volunteer.repository.VolunteerRepository; import com.somemore.volunteer.usecase.RegisterVolunteerUseCase; diff --git a/src/main/java/com/somemore/volunteerApply/domain/VolunteerApply.java b/src/main/java/com/somemore/volunteerApply/domain/VolunteerApply.java index da51dff6d..b687a4229 100644 --- a/src/main/java/com/somemore/volunteerApply/domain/VolunteerApply.java +++ b/src/main/java/com/somemore/volunteerApply/domain/VolunteerApply.java @@ -27,17 +27,17 @@ public class VolunteerApply extends BaseEntity { @Enumerated(EnumType.STRING) @Column(name = "status", nullable = false, length = 20) - private ApplyStatus status; + private ApplyStatus status = ApplyStatus.WAITING; @Column(name = "attended", nullable = false) - private Boolean attended; + private Boolean attended = false; @Builder public VolunteerApply(UUID volunteerId, Long recruitBoardId, ApplyStatus status, Boolean attended) { this.volunteerId = volunteerId; this.recruitBoardId = recruitBoardId; - this.status = status != null ? status : ApplyStatus.WAITING; - this.attended = attended != null ? attended : false; + this.status = status; + this.attended = attended; } } diff --git a/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImpl.java b/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImpl.java index ed3733d02..56f654476 100644 --- a/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImpl.java +++ b/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImpl.java @@ -23,7 +23,7 @@ public class VolunteerApplyRepositoryImpl implements VolunteerApplyRepository { private final VolunteerApplyJpaRepository volunteerApplyJpaRepository; private final JPAQueryFactory queryFactory; - private final QVolunteerApply volunteerApply = QVolunteerApply.volunteerApply; + private static final QVolunteerApply volunteerApply = QVolunteerApply.volunteerApply; @Override public VolunteerApply save(VolunteerApply volunteerApply) { diff --git a/src/test/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImplTest.java b/src/test/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImplTest.java index 5fe2b731b..1f320beda 100644 --- a/src/test/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImplTest.java +++ b/src/test/java/com/somemore/recruitboard/repository/RecruitBoardRepositoryImplTest.java @@ -247,9 +247,7 @@ void findNotCompletedIdsByCenterIds() { // then assertThat(notCompletedBoardIds) - .hasSize(2); - - assertThat(notCompletedBoardIds) + .hasSize(2) .doesNotContain(deletedRecruitingBoard.getId()) .doesNotContain(deletedClosedBoard.getId()) .doesNotContain(deletedCompletedRecruitBoard.getId()) From 7009cf1be664169ae1e02f9c9c1ba67b51f1a1ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sun, 1 Dec 2024 00:41:20 +0900 Subject: [PATCH 50/54] =?UTF-8?q?fix(VolunteerApplyQueryServiceTest):=20bu?= =?UTF-8?q?ilder=EB=8A=94=20=EA=B8=B0=EB=B3=B8=20=EA=B0=92=EC=9D=B4=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/VolunteerApplyQueryServiceTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/somemore/volunteerApply/service/VolunteerApplyQueryServiceTest.java b/src/test/java/com/somemore/volunteerApply/service/VolunteerApplyQueryServiceTest.java index 4c53a37cb..dd079352c 100644 --- a/src/test/java/com/somemore/volunteerApply/service/VolunteerApplyQueryServiceTest.java +++ b/src/test/java/com/somemore/volunteerApply/service/VolunteerApplyQueryServiceTest.java @@ -1,6 +1,7 @@ package com.somemore.volunteerApply.service; import com.somemore.IntegrationTestSupport; +import com.somemore.volunteerApply.domain.ApplyStatus; import com.somemore.volunteerApply.domain.VolunteerApply; import com.somemore.volunteerApply.repository.VolunteerApplyRepository; import org.junit.jupiter.api.DisplayName; @@ -50,8 +51,8 @@ private VolunteerApply createVolunteerApply(Long recruitId, UUID volunteerId) { return VolunteerApply.builder() .volunteerId(volunteerId) .recruitBoardId(recruitId) - .status(null) - .attended(null) + .status(ApplyStatus.WAITING) + .attended(false) .build(); } } \ No newline at end of file From 29a621ba56c29332c488f6dc34c3ecb5791aa6bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sun, 1 Dec 2024 00:49:49 +0900 Subject: [PATCH 51/54] =?UTF-8?q?refactor(VolunteerQueryService):=20?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=9C=BC=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../somemore/volunteer/service/VolunteerQueryService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java b/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java index 1bb761f10..5e69dddbc 100644 --- a/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java +++ b/src/main/java/com/somemore/volunteer/service/VolunteerQueryService.java @@ -1,6 +1,6 @@ package com.somemore.volunteer.service; -import com.somemore.facade.validator.VolunteerDetailAccessValidatorImpl; +import com.somemore.facade.validator.VolunteerDetailAccessValidator; import com.somemore.global.exception.BadRequestException; import com.somemore.volunteer.domain.Volunteer; import com.somemore.volunteer.domain.VolunteerDetail; @@ -25,7 +25,7 @@ public class VolunteerQueryService implements VolunteerQueryUseCase { private final VolunteerRepository volunteerRepository; private final VolunteerDetailRepository volunteerDetailRepository; - private final VolunteerDetailAccessValidatorImpl volunteerDetailAccessValidatorImpl; + private final VolunteerDetailAccessValidator volunteerDetailAccessValidator; @Override public VolunteerResponseDto getMyProfile(UUID volunteerId) { @@ -46,7 +46,7 @@ public VolunteerResponseDto getVolunteerProfile(UUID volunteerId) { @Override public VolunteerResponseDto getVolunteerDetailedProfile(UUID volunteerId, UUID centerId) { - volunteerDetailAccessValidatorImpl.validateByCenterId(centerId, volunteerId); + volunteerDetailAccessValidator.validateByCenterId(centerId, volunteerId); return VolunteerResponseDto.from( findVolunteer(volunteerId), From 20ca50deee97dc65b1ac2f371fc4a37065469a72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sun, 1 Dec 2024 01:59:40 +0900 Subject: [PATCH 52/54] =?UTF-8?q?test(VolunteerResponseDto):=20=EB=B4=89?= =?UTF-8?q?=EC=82=AC=EC=9E=90=20=EC=9D=91=EB=8B=B5=20=EC=A0=95=EB=B3=B4=20?= =?UTF-8?q?=EC=8A=A4=EC=9B=A8=EA=B1=B0=20=EC=96=B4=EB=85=B8=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/VolunteerResponseDto.java | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/somemore/volunteer/dto/response/VolunteerResponseDto.java b/src/main/java/com/somemore/volunteer/dto/response/VolunteerResponseDto.java index 37725f14c..9884804b9 100644 --- a/src/main/java/com/somemore/volunteer/dto/response/VolunteerResponseDto.java +++ b/src/main/java/com/somemore/volunteer/dto/response/VolunteerResponseDto.java @@ -1,16 +1,36 @@ package com.somemore.volunteer.dto.response; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.databind.annotation.JsonNaming; import com.somemore.volunteer.domain.Volunteer; import com.somemore.volunteer.domain.VolunteerDetail; +import io.swagger.v3.oas.annotations.media.Schema; +@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +@Schema(description = "봉사자 응답 DTO") public record VolunteerResponseDto( + @Schema(description = "봉사자 ID", example = "123e4567-e89b-12d3-a456-426614174000") String volunteerId, + + @Schema(description = "봉사자 닉네임", example = "길동이") String nickname, + + @Schema(description = "봉사자 이미지 URL", example = "http://example.com/image.jpg") String imgUrl, + + @Schema(description = "봉사자 소개", example = "안녕하세요! 봉사 활동을 좋아합니다.") String introduce, + + @Schema(description = "봉사자 등급", example = "RED") String tier, + + @Schema(description = "총 봉사 시간", example = "120") Integer totalVolunteerHours, + + @Schema(description = "총 봉사 횟수", example = "20") Integer totalVolunteerCount, + + @Schema(description = "봉사자 상세 정보", implementation = VolunteerDetailResponseDto.class) VolunteerDetailResponseDto volunteerDetailResponseDto ) { @@ -45,11 +65,22 @@ public static VolunteerResponseDto from( ); } + @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) + @Schema(description = "봉사자 상세 응답 DTO") private record VolunteerDetailResponseDto( + @Schema(description = "이름", example = "홍길동") String name, + + @Schema(description = "이메일", example = "honggildong@example.com") String email, + + @Schema(description = "성별", example = "MALE") String gender, + + @Schema(description = "생년월일", example = "1990-01-01") String birthDate, + + @Schema(description = "연락처", example = "010-1234-5678") String contactNumber ) { public static VolunteerDetailResponseDto from( @@ -64,8 +95,4 @@ public static VolunteerDetailResponseDto from( ); } } - - } - - From 6f425ef28ff34a37c04685b67012377e69df8b22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sun, 1 Dec 2024 02:02:21 +0900 Subject: [PATCH 53/54] =?UTF-8?q?chore(package):=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=EC=9D=B4=EB=A6=84=20=EB=8C=80=EB=AC=B8=EC=9E=90=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../validator/VolunteerDetailAccessValidatorImpl.java | 2 +- .../domain/ApplyStatus.java | 2 +- .../domain/VolunteerApply.java | 2 +- .../repository/VolunteerApplyJpaRepository.java | 4 ++-- .../repository/VolunteerApplyRepository.java | 4 ++-- .../repository/VolunteerApplyRepositoryImpl.java | 6 +++--- .../service/VolunteerApplyQueryService.java | 6 +++--- .../usecase/VolunteerApplyQueryUseCase.java | 2 +- .../validator/VolunteerDetailAccessValidatorImplTest.java | 6 +++--- .../repository/VolunteerApplyRepositoryImplTest.java | 6 +++--- .../service/VolunteerApplyQueryServiceTest.java | 8 ++++---- 11 files changed, 24 insertions(+), 24 deletions(-) rename src/main/java/com/somemore/{volunteerApply => volunteerapply}/domain/ApplyStatus.java (61%) rename src/main/java/com/somemore/{volunteerApply => volunteerapply}/domain/VolunteerApply.java (96%) rename src/main/java/com/somemore/{volunteerApply => volunteerapply}/repository/VolunteerApplyJpaRepository.java (59%) rename src/main/java/com/somemore/{volunteerApply => volunteerapply}/repository/VolunteerApplyRepository.java (81%) rename src/main/java/com/somemore/{volunteerApply => volunteerapply}/repository/VolunteerApplyRepositoryImpl.java (95%) rename src/main/java/com/somemore/{volunteerApply => volunteerapply}/service/VolunteerApplyQueryService.java (79%) rename src/main/java/com/somemore/{volunteerApply => volunteerapply}/usecase/VolunteerApplyQueryUseCase.java (78%) rename src/test/java/com/somemore/{volunteerApply => volunteerapply}/repository/VolunteerApplyRepositoryImplTest.java (95%) rename src/test/java/com/somemore/{volunteerApply => volunteerapply}/service/VolunteerApplyQueryServiceTest.java (88%) diff --git a/src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImpl.java b/src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImpl.java index 681d67fbc..05e66075b 100644 --- a/src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImpl.java +++ b/src/main/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImpl.java @@ -2,7 +2,7 @@ import com.somemore.global.exception.BadRequestException; import com.somemore.recruitboard.usecase.query.RecruitBoardQueryUseCase; -import com.somemore.volunteerApply.usecase.VolunteerApplyQueryUseCase; +import com.somemore.volunteerapply.usecase.VolunteerApplyQueryUseCase; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/somemore/volunteerApply/domain/ApplyStatus.java b/src/main/java/com/somemore/volunteerapply/domain/ApplyStatus.java similarity index 61% rename from src/main/java/com/somemore/volunteerApply/domain/ApplyStatus.java rename to src/main/java/com/somemore/volunteerapply/domain/ApplyStatus.java index eddb7b073..aa6634759 100644 --- a/src/main/java/com/somemore/volunteerApply/domain/ApplyStatus.java +++ b/src/main/java/com/somemore/volunteerapply/domain/ApplyStatus.java @@ -1,4 +1,4 @@ -package com.somemore.volunteerApply.domain; +package com.somemore.volunteerapply.domain; public enum ApplyStatus { WAITING, diff --git a/src/main/java/com/somemore/volunteerApply/domain/VolunteerApply.java b/src/main/java/com/somemore/volunteerapply/domain/VolunteerApply.java similarity index 96% rename from src/main/java/com/somemore/volunteerApply/domain/VolunteerApply.java rename to src/main/java/com/somemore/volunteerapply/domain/VolunteerApply.java index b687a4229..05715b88e 100644 --- a/src/main/java/com/somemore/volunteerApply/domain/VolunteerApply.java +++ b/src/main/java/com/somemore/volunteerapply/domain/VolunteerApply.java @@ -1,4 +1,4 @@ -package com.somemore.volunteerApply.domain; +package com.somemore.volunteerapply.domain; import com.somemore.global.common.BaseEntity; import jakarta.persistence.*; diff --git a/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyJpaRepository.java b/src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyJpaRepository.java similarity index 59% rename from src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyJpaRepository.java rename to src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyJpaRepository.java index 1b51573ec..edee536e6 100644 --- a/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyJpaRepository.java +++ b/src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyJpaRepository.java @@ -1,6 +1,6 @@ -package com.somemore.volunteerApply.repository; +package com.somemore.volunteerapply.repository; -import com.somemore.volunteerApply.domain.VolunteerApply; +import com.somemore.volunteerapply.domain.VolunteerApply; import org.springframework.data.jpa.repository.JpaRepository; public interface VolunteerApplyJpaRepository extends JpaRepository { diff --git a/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepository.java b/src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyRepository.java similarity index 81% rename from src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepository.java rename to src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyRepository.java index 05e55486a..5f68b0c95 100644 --- a/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepository.java +++ b/src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyRepository.java @@ -1,6 +1,6 @@ -package com.somemore.volunteerApply.repository; +package com.somemore.volunteerapply.repository; -import com.somemore.volunteerApply.domain.VolunteerApply; +import com.somemore.volunteerapply.domain.VolunteerApply; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; diff --git a/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImpl.java b/src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyRepositoryImpl.java similarity index 95% rename from src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImpl.java rename to src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyRepositoryImpl.java index 56f654476..61112ce1b 100644 --- a/src/main/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImpl.java +++ b/src/main/java/com/somemore/volunteerapply/repository/VolunteerApplyRepositoryImpl.java @@ -1,10 +1,10 @@ -package com.somemore.volunteerApply.repository; +package com.somemore.volunteerapply.repository; import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQueryFactory; -import com.somemore.volunteerApply.domain.QVolunteerApply; -import com.somemore.volunteerApply.domain.VolunteerApply; +import com.somemore.volunteerapply.domain.QVolunteerApply; +import com.somemore.volunteerapply.domain.VolunteerApply; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; diff --git a/src/main/java/com/somemore/volunteerApply/service/VolunteerApplyQueryService.java b/src/main/java/com/somemore/volunteerapply/service/VolunteerApplyQueryService.java similarity index 79% rename from src/main/java/com/somemore/volunteerApply/service/VolunteerApplyQueryService.java rename to src/main/java/com/somemore/volunteerapply/service/VolunteerApplyQueryService.java index 5b36013cc..100765e23 100644 --- a/src/main/java/com/somemore/volunteerApply/service/VolunteerApplyQueryService.java +++ b/src/main/java/com/somemore/volunteerapply/service/VolunteerApplyQueryService.java @@ -1,7 +1,7 @@ -package com.somemore.volunteerApply.service; +package com.somemore.volunteerapply.service; -import com.somemore.volunteerApply.repository.VolunteerApplyRepository; -import com.somemore.volunteerApply.usecase.VolunteerApplyQueryUseCase; +import com.somemore.volunteerapply.repository.VolunteerApplyRepository; +import com.somemore.volunteerapply.usecase.VolunteerApplyQueryUseCase; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/somemore/volunteerApply/usecase/VolunteerApplyQueryUseCase.java b/src/main/java/com/somemore/volunteerapply/usecase/VolunteerApplyQueryUseCase.java similarity index 78% rename from src/main/java/com/somemore/volunteerApply/usecase/VolunteerApplyQueryUseCase.java rename to src/main/java/com/somemore/volunteerapply/usecase/VolunteerApplyQueryUseCase.java index e1795ef83..e7ab746b2 100644 --- a/src/main/java/com/somemore/volunteerApply/usecase/VolunteerApplyQueryUseCase.java +++ b/src/main/java/com/somemore/volunteerapply/usecase/VolunteerApplyQueryUseCase.java @@ -1,4 +1,4 @@ -package com.somemore.volunteerApply.usecase; +package com.somemore.volunteerapply.usecase; import java.util.List; import java.util.UUID; diff --git a/src/test/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImplTest.java b/src/test/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImplTest.java index d5031792e..4a12684b6 100644 --- a/src/test/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImplTest.java +++ b/src/test/java/com/somemore/facade/validator/VolunteerDetailAccessValidatorImplTest.java @@ -4,9 +4,9 @@ import com.somemore.global.exception.BadRequestException; import com.somemore.recruitboard.domain.RecruitBoard; import com.somemore.recruitboard.repository.RecruitBoardRepository; -import com.somemore.volunteerApply.domain.ApplyStatus; -import com.somemore.volunteerApply.domain.VolunteerApply; -import com.somemore.volunteerApply.repository.VolunteerApplyRepository; +import com.somemore.volunteerapply.domain.ApplyStatus; +import com.somemore.volunteerapply.domain.VolunteerApply; +import com.somemore.volunteerapply.repository.VolunteerApplyRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/test/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImplTest.java b/src/test/java/com/somemore/volunteerapply/repository/VolunteerApplyRepositoryImplTest.java similarity index 95% rename from src/test/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImplTest.java rename to src/test/java/com/somemore/volunteerapply/repository/VolunteerApplyRepositoryImplTest.java index cb296420d..7792a3967 100644 --- a/src/test/java/com/somemore/volunteerApply/repository/VolunteerApplyRepositoryImplTest.java +++ b/src/test/java/com/somemore/volunteerapply/repository/VolunteerApplyRepositoryImplTest.java @@ -1,8 +1,8 @@ -package com.somemore.volunteerApply.repository; +package com.somemore.volunteerapply.repository; import com.somemore.IntegrationTestSupport; -import com.somemore.volunteerApply.domain.VolunteerApply; -import com.somemore.volunteerApply.domain.ApplyStatus; +import com.somemore.volunteerapply.domain.VolunteerApply; +import com.somemore.volunteerapply.domain.ApplyStatus; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/somemore/volunteerApply/service/VolunteerApplyQueryServiceTest.java b/src/test/java/com/somemore/volunteerapply/service/VolunteerApplyQueryServiceTest.java similarity index 88% rename from src/test/java/com/somemore/volunteerApply/service/VolunteerApplyQueryServiceTest.java rename to src/test/java/com/somemore/volunteerapply/service/VolunteerApplyQueryServiceTest.java index dd079352c..96168a3d1 100644 --- a/src/test/java/com/somemore/volunteerApply/service/VolunteerApplyQueryServiceTest.java +++ b/src/test/java/com/somemore/volunteerapply/service/VolunteerApplyQueryServiceTest.java @@ -1,9 +1,9 @@ -package com.somemore.volunteerApply.service; +package com.somemore.volunteerapply.service; import com.somemore.IntegrationTestSupport; -import com.somemore.volunteerApply.domain.ApplyStatus; -import com.somemore.volunteerApply.domain.VolunteerApply; -import com.somemore.volunteerApply.repository.VolunteerApplyRepository; +import com.somemore.volunteerapply.domain.ApplyStatus; +import com.somemore.volunteerapply.domain.VolunteerApply; +import com.somemore.volunteerapply.repository.VolunteerApplyRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; From bef0ddbe0f0ccc5f852d85fe1cf01c6b81b88ebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Sun, 1 Dec 2024 17:41:32 +0900 Subject: [PATCH 54/54] =?UTF-8?q?style(=EA=B0=9C=ED=96=89):=20git=20?= =?UTF-8?q?=EC=9E=A0=EC=9E=AC=EC=A0=81=EC=9D=B8=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=EC=98=88=EB=B0=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../somemore/volunteer/repository/VolunteerRepositoryImpl.java | 2 +- .../java/com/somemore/volunteerapply/domain/VolunteerApply.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java b/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java index fcda52d4a..779d04cac 100644 --- a/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java +++ b/src/main/java/com/somemore/volunteer/repository/VolunteerRepositoryImpl.java @@ -76,4 +76,4 @@ private Optional findDynamicField(UUID id, Path field) { private BooleanExpression isNotDeleted() { return volunteer.deleted.isFalse(); } -} \ No newline at end of file +} diff --git a/src/main/java/com/somemore/volunteerapply/domain/VolunteerApply.java b/src/main/java/com/somemore/volunteerapply/domain/VolunteerApply.java index 05715b88e..64ceaf9c1 100644 --- a/src/main/java/com/somemore/volunteerapply/domain/VolunteerApply.java +++ b/src/main/java/com/somemore/volunteerapply/domain/VolunteerApply.java @@ -41,4 +41,4 @@ public VolunteerApply(UUID volunteerId, Long recruitBoardId, ApplyStatus status, } } -// TODO 상태 업데이트 메서드들을 만들고 빌더에서 status를 변경 불가하도록 \ No newline at end of file +// TODO 상태 업데이트 메서드들을 만들고 빌더에서 status를 변경 불가하도록