diff --git a/src/main/java/com/somemore/interestcenter/controller/InterestCenterCommandApiController.java b/src/main/java/com/somemore/interestcenter/controller/InterestCenterCommandApiController.java index bcd3df349..9f00ef66e 100644 --- a/src/main/java/com/somemore/interestcenter/controller/InterestCenterCommandApiController.java +++ b/src/main/java/com/somemore/interestcenter/controller/InterestCenterCommandApiController.java @@ -1,5 +1,6 @@ package com.somemore.interestcenter.controller; +import com.somemore.auth.annotation.CurrentUser; import com.somemore.global.common.response.ApiResponse; import com.somemore.interestcenter.dto.request.RegisterInterestCenterRequestDto; import com.somemore.interestcenter.dto.response.RegisterInterestCenterResponseDto; @@ -8,8 +9,14 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; +import java.util.UUID; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.*; +import org.springframework.security.access.annotation.Secured; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; @RequiredArgsConstructor @RestController @@ -19,20 +26,26 @@ public class InterestCenterCommandApiController { private final RegisterInterestCenterUseCase registerInterestCenterUseCase; private final CancelInterestCenterUseCase cancelInterestCenterUseCase; + @Secured("ROLE_VOLUNTEER") @Operation(summary = "관심기관 등록 API") @PostMapping("/api/interest-center") - public ApiResponse registerInterestCenter(@Valid @RequestBody RegisterInterestCenterRequestDto requestDto) { + public ApiResponse registerInterestCenter( + @CurrentUser UUID volunteerId, + @Valid @RequestBody RegisterInterestCenterRequestDto requestDto) { - RegisterInterestCenterResponseDto responseDto = registerInterestCenterUseCase.registerInterestCenter(requestDto); + RegisterInterestCenterResponseDto responseDto = registerInterestCenterUseCase.registerInterestCenter(volunteerId, requestDto); return ApiResponse.ok(200, responseDto, "관심 기관 등록 성공"); } + @Secured("ROLE_VOLUNTEER") @Operation(summary = "관심기관 취소 API") - @DeleteMapping("/api/interest-center/{interest-center-id}") - public ApiResponse deleteInterestCenter(@PathVariable("interest-center-id") Long interestCenterId) { + @DeleteMapping("/api/interest-center/{centerId}") + public ApiResponse deleteInterestCenter( + @CurrentUser UUID volunteerId, + @PathVariable UUID centerId) { - cancelInterestCenterUseCase.cancelInterestCenter(interestCenterId); + cancelInterestCenterUseCase.cancelInterestCenter(volunteerId, centerId); return ApiResponse.ok("관심 기관 취소 성공"); } diff --git a/src/main/java/com/somemore/interestcenter/dto/request/RegisterInterestCenterRequestDto.java b/src/main/java/com/somemore/interestcenter/dto/request/RegisterInterestCenterRequestDto.java index beb917c84..4e17b29d6 100644 --- a/src/main/java/com/somemore/interestcenter/dto/request/RegisterInterestCenterRequestDto.java +++ b/src/main/java/com/somemore/interestcenter/dto/request/RegisterInterestCenterRequestDto.java @@ -11,15 +11,11 @@ @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) public record RegisterInterestCenterRequestDto( - @Schema(description = "봉사자 ID", example = "123e4567-e89b-12d3-a456-426614174000") - @NotNull(message = "봉사자 ID는 필수값입니다.") - UUID volunteerId, - @Schema(description = "기관 ID", example = "123e4567-e89b-12d3-a456-426614174000") @NotNull(message = "기관 ID는 필수값입니다.") UUID centerId ) { - public InterestCenter toEntity(){ + public InterestCenter toEntity(UUID volunteerId){ return InterestCenter.create(volunteerId, centerId); } } diff --git a/src/main/java/com/somemore/interestcenter/repository/InterestCenterRepository.java b/src/main/java/com/somemore/interestcenter/repository/InterestCenterRepository.java index 4292d2c4f..70922763f 100644 --- a/src/main/java/com/somemore/interestcenter/repository/InterestCenterRepository.java +++ b/src/main/java/com/somemore/interestcenter/repository/InterestCenterRepository.java @@ -13,4 +13,5 @@ public interface InterestCenterRepository { Optional findInterestCenterResponseById(Long id); List findInterestCenterIdsByVolunteerId(UUID volunteerId); boolean existsByVolunteerIdAndCenterId(UUID volunteerId, UUID centerId); + Optional findByVolunteerIdAndCenterId(UUID volunteerId, UUID centerId); } diff --git a/src/main/java/com/somemore/interestcenter/repository/InterestCenterRepositoryImpl.java b/src/main/java/com/somemore/interestcenter/repository/InterestCenterRepositoryImpl.java index b5f10c65c..1d452eb0b 100644 --- a/src/main/java/com/somemore/interestcenter/repository/InterestCenterRepositoryImpl.java +++ b/src/main/java/com/somemore/interestcenter/repository/InterestCenterRepositoryImpl.java @@ -5,12 +5,11 @@ import com.somemore.interestcenter.domain.InterestCenter; import com.somemore.interestcenter.domain.QInterestCenter; import com.somemore.interestcenter.dto.response.RegisterInterestCenterResponseDto; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Repository; - import java.util.List; import java.util.Optional; import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; @RequiredArgsConstructor @Repository @@ -93,4 +92,18 @@ public boolean existsByVolunteerIdAndCenterId(UUID volunteerId, UUID centerId) { return result != null; } + @Override + public Optional findByVolunteerIdAndCenterId(UUID volunteerId, UUID centerId) { + QInterestCenter interestCenter = QInterestCenter.interestCenter; + + InterestCenter result = queryFactory.selectFrom(interestCenter) + .where( + interestCenter.volunteerId.eq(volunteerId) + .and(interestCenter.centerId.eq(centerId)) + .and(interestCenter.deleted.isFalse())) + .fetchOne(); + + return Optional.ofNullable(result); + } + } diff --git a/src/main/java/com/somemore/interestcenter/service/CancelInterestCenterService.java b/src/main/java/com/somemore/interestcenter/service/CancelInterestCenterService.java index a3c72145c..711214b5c 100644 --- a/src/main/java/com/somemore/interestcenter/service/CancelInterestCenterService.java +++ b/src/main/java/com/somemore/interestcenter/service/CancelInterestCenterService.java @@ -1,9 +1,11 @@ package com.somemore.interestcenter.service; +import com.somemore.center.usecase.query.CenterQueryUseCase; import com.somemore.global.exception.BadRequestException; import com.somemore.interestcenter.domain.InterestCenter; import com.somemore.interestcenter.repository.InterestCenterRepository; import com.somemore.interestcenter.usecase.CancelInterestCenterUseCase; +import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -14,10 +16,13 @@ public class CancelInterestCenterService implements CancelInterestCenterUseCase { private final InterestCenterRepository interestCenterRepository; + private final CenterQueryUseCase centerQueryUseCase; @Override - public void cancelInterestCenter(Long interestCenterId) { - InterestCenter interestCenter = interestCenterRepository.findById(interestCenterId) + public void cancelInterestCenter(UUID volunteerId, UUID centerId) { + centerQueryUseCase.validateCenterExists(centerId); + + InterestCenter interestCenter = interestCenterRepository.findByVolunteerIdAndCenterId(volunteerId, centerId) .orElseThrow(() -> new BadRequestException(CANNOT_CANCEL_DELETED_INTEREST_CENTER.getMessage())); interestCenter.markAsDeleted(); diff --git a/src/main/java/com/somemore/interestcenter/service/RegisterInterestCenterService.java b/src/main/java/com/somemore/interestcenter/service/RegisterInterestCenterService.java index c9fb8ce3d..11244c595 100644 --- a/src/main/java/com/somemore/interestcenter/service/RegisterInterestCenterService.java +++ b/src/main/java/com/somemore/interestcenter/service/RegisterInterestCenterService.java @@ -7,6 +7,7 @@ import com.somemore.interestcenter.dto.response.RegisterInterestCenterResponseDto; import com.somemore.interestcenter.repository.InterestCenterRepository; import com.somemore.interestcenter.usecase.RegisterInterestCenterUseCase; +import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -20,16 +21,16 @@ public class RegisterInterestCenterService implements RegisterInterestCenterUseC private final CenterQueryUseCase centerQueryUseCase; @Override - public RegisterInterestCenterResponseDto registerInterestCenter(RegisterInterestCenterRequestDto requestDto) { + public RegisterInterestCenterResponseDto registerInterestCenter(UUID volunteerId, RegisterInterestCenterRequestDto requestDto) { centerQueryUseCase.validateCenterExists(requestDto.centerId()); - boolean isDuplicate = repository.existsByVolunteerIdAndCenterId(requestDto.volunteerId(), requestDto.centerId()); + boolean isDuplicate = repository.existsByVolunteerIdAndCenterId(volunteerId, requestDto.centerId()); if(isDuplicate){ throw new DuplicateException(DUPLICATE_INTEREST_CENTER.getMessage()); } - InterestCenter interestCenter = repository.save(requestDto.toEntity()); + InterestCenter interestCenter = repository.save(requestDto.toEntity(volunteerId)); return RegisterInterestCenterResponseDto.from(interestCenter); } diff --git a/src/main/java/com/somemore/interestcenter/usecase/CancelInterestCenterUseCase.java b/src/main/java/com/somemore/interestcenter/usecase/CancelInterestCenterUseCase.java index 53515a1cd..0924cf7e6 100644 --- a/src/main/java/com/somemore/interestcenter/usecase/CancelInterestCenterUseCase.java +++ b/src/main/java/com/somemore/interestcenter/usecase/CancelInterestCenterUseCase.java @@ -1,5 +1,7 @@ package com.somemore.interestcenter.usecase; +import java.util.UUID; + public interface CancelInterestCenterUseCase { - void cancelInterestCenter(Long interestCenterId); + void cancelInterestCenter(UUID volunteerId, UUID centerId); } diff --git a/src/main/java/com/somemore/interestcenter/usecase/RegisterInterestCenterUseCase.java b/src/main/java/com/somemore/interestcenter/usecase/RegisterInterestCenterUseCase.java index f6ce68e7a..b68647848 100644 --- a/src/main/java/com/somemore/interestcenter/usecase/RegisterInterestCenterUseCase.java +++ b/src/main/java/com/somemore/interestcenter/usecase/RegisterInterestCenterUseCase.java @@ -2,7 +2,8 @@ import com.somemore.interestcenter.dto.request.RegisterInterestCenterRequestDto; import com.somemore.interestcenter.dto.response.RegisterInterestCenterResponseDto; +import java.util.UUID; public interface RegisterInterestCenterUseCase { - RegisterInterestCenterResponseDto registerInterestCenter(RegisterInterestCenterRequestDto requestDto); + RegisterInterestCenterResponseDto registerInterestCenter(UUID volunteerId, RegisterInterestCenterRequestDto requestDto); } diff --git a/src/test/java/com/somemore/interestcenter/controller/InterestCenterCommandApiControllerTest.java b/src/test/java/com/somemore/interestcenter/controller/InterestCenterCommandApiControllerTest.java index a49476b02..f49939e5a 100644 --- a/src/test/java/com/somemore/interestcenter/controller/InterestCenterCommandApiControllerTest.java +++ b/src/test/java/com/somemore/interestcenter/controller/InterestCenterCommandApiControllerTest.java @@ -1,6 +1,7 @@ package com.somemore.interestcenter.controller; import com.somemore.ControllerTestSupport; +import com.somemore.WithMockCustomUser; import com.somemore.interestcenter.dto.request.RegisterInterestCenterRequestDto; import com.somemore.interestcenter.dto.response.RegisterInterestCenterResponseDto; import com.somemore.interestcenter.usecase.CancelInterestCenterUseCase; @@ -11,6 +12,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import java.util.UUID; +import org.springframework.security.test.context.support.WithMockUser; import static org.mockito.BDDMockito.given; import static org.mockito.ArgumentMatchers.any; @@ -31,16 +33,18 @@ class InterestCenterCommandApiControllerTest extends ControllerTestSupport { @BeforeEach void setUp() { requestDto = new RegisterInterestCenterRequestDto( - UUID.fromString("123e4567-e89b-12d3-a456-426614174000"), UUID.fromString("123e4567-e89b-12d3-a456-426614174000") ); } + @WithMockCustomUser @Test void registerInterestCenter_ShouldReturnSuccess() throws Exception { // given - RegisterInterestCenterResponseDto responseDto = new RegisterInterestCenterResponseDto(1L, requestDto.volunteerId(), requestDto.centerId()); - given(registerInterestCenterUseCase.registerInterestCenter(any(RegisterInterestCenterRequestDto.class))) + UUID volunteerId = UUID.randomUUID(); + + RegisterInterestCenterResponseDto responseDto = new RegisterInterestCenterResponseDto(1L, volunteerId, requestDto.centerId()); + given(registerInterestCenterUseCase.registerInterestCenter(any(UUID.class), any(RegisterInterestCenterRequestDto.class))) .willReturn(responseDto); // when & then @@ -54,14 +58,15 @@ void registerInterestCenter_ShouldReturnSuccess() throws Exception { .andExpect(jsonPath("$.data.center_id").value(responseDto.centerId().toString())); } + @WithMockCustomUser @Test void deleteInterestCenter_ShouldReturnSuccess() throws Exception { // given - Long interestCenterId = 1L; - doNothing().when(cancelInterestCenterUseCase).cancelInterestCenter(interestCenterId); + UUID centerId = UUID.randomUUID(); + doNothing().when(cancelInterestCenterUseCase).cancelInterestCenter(any(UUID.class), any(UUID.class)); // when & then - mockMvc.perform(delete("/api/interest-center/{interest-center-id}", interestCenterId)) + mockMvc.perform(delete("/api/interest-center/{centerId}", centerId)) .andExpect(status().isOk()) .andExpect(jsonPath("$.message").value("관심 기관 취소 성공")); } diff --git a/src/test/java/com/somemore/interestcenter/repository/InterestCenterRepositoryImplTest.java b/src/test/java/com/somemore/interestcenter/repository/InterestCenterRepositoryImplTest.java new file mode 100644 index 000000000..c037f1f0c --- /dev/null +++ b/src/test/java/com/somemore/interestcenter/repository/InterestCenterRepositoryImplTest.java @@ -0,0 +1,41 @@ +package com.somemore.interestcenter.repository; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.somemore.IntegrationTestSupport; +import com.somemore.interestcenter.domain.InterestCenter; +import java.util.Optional; +import java.util.UUID; +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; + +@Transactional +class InterestCenterRepositoryImplTest extends IntegrationTestSupport { + + @Autowired + private InterestCenterRepository interestCenterRepository; + + @DisplayName("봉사자 아이디와 기관 아이디로 관심 기관을 조회할 수 있다.") + @Test + void findByVolunteerIdAndCenterId() { + // given + UUID centerId = UUID.randomUUID(); + UUID volunteerId = UUID.randomUUID(); + + InterestCenter interestCenter = InterestCenter.create(volunteerId, centerId); + + interestCenterRepository.save(interestCenter); + + // when + Optional result = interestCenterRepository.findByVolunteerIdAndCenterId( + volunteerId, centerId); + + // then + assertThat(result).isPresent(); + assertThat(result.get().getCenterId()).isEqualTo(centerId); + assertThat(result.get().getVolunteerId()).isEqualTo(volunteerId); + } + +} diff --git a/src/test/java/com/somemore/interestcenter/service/CancelInterestCenterServiceTest.java b/src/test/java/com/somemore/interestcenter/service/CancelInterestCenterServiceTest.java index b756865fd..a174f7302 100644 --- a/src/test/java/com/somemore/interestcenter/service/CancelInterestCenterServiceTest.java +++ b/src/test/java/com/somemore/interestcenter/service/CancelInterestCenterServiceTest.java @@ -43,16 +43,16 @@ void CancelInterestCenter() { Center center = createCenter(); UUID volunteerId = UUID.fromString("123e4567-e89b-12d3-a456-426614174000"); UUID centerId = center.getId(); - RegisterInterestCenterRequestDto requestDto = new RegisterInterestCenterRequestDto(volunteerId, centerId); + RegisterInterestCenterRequestDto requestDto = new RegisterInterestCenterRequestDto(centerId); - RegisterInterestCenterResponseDto responseDto = registerInterestCenterUseCase.registerInterestCenter(requestDto); + RegisterInterestCenterResponseDto responseDto = registerInterestCenterUseCase.registerInterestCenter(volunteerId, requestDto); InterestCenter savedInterestCenter = interestCenterRepository.findById(responseDto.id()) .orElseThrow(() -> new IllegalStateException("등록된 관심 기관이 없습니다.")); assertEquals(savedInterestCenter.getId(), responseDto.id()); //when - cancelInterestCenterUseCase.cancelInterestCenter(responseDto.id()); + cancelInterestCenterUseCase.cancelInterestCenter(volunteerId, centerId); //then Optional deletedInterestCenterOptional = interestCenterRepository.findById(responseDto.id()); @@ -67,14 +67,13 @@ void cancelInterestCenter_AlreadyDeleted_ShouldThrowException() { Center center = createCenter(); UUID volunteerId = UUID.fromString("123e4567-e89b-12d3-a456-426614174000"); UUID centerId = center.getId(); - RegisterInterestCenterRequestDto requestDto = new RegisterInterestCenterRequestDto(volunteerId, centerId); - RegisterInterestCenterResponseDto responseDto = registerInterestCenterUseCase.registerInterestCenter(requestDto); - cancelInterestCenterUseCase.cancelInterestCenter(responseDto.id()); + RegisterInterestCenterRequestDto requestDto = new RegisterInterestCenterRequestDto(centerId); + RegisterInterestCenterResponseDto responseDto = registerInterestCenterUseCase.registerInterestCenter(volunteerId, requestDto); + cancelInterestCenterUseCase.cancelInterestCenter(volunteerId, centerId); //when, then - long interestCenterId = responseDto.id(); assertThrows(BadRequestException.class, - () -> cancelInterestCenterUseCase.cancelInterestCenter(interestCenterId), + () -> cancelInterestCenterUseCase.cancelInterestCenter(volunteerId, centerId), CANNOT_CANCEL_DELETED_INTEREST_CENTER.getMessage() ); } diff --git a/src/test/java/com/somemore/interestcenter/service/RegisterInterestCenterServiceTest.java b/src/test/java/com/somemore/interestcenter/service/RegisterInterestCenterServiceTest.java index a979c37d5..23e5f528f 100644 --- a/src/test/java/com/somemore/interestcenter/service/RegisterInterestCenterServiceTest.java +++ b/src/test/java/com/somemore/interestcenter/service/RegisterInterestCenterServiceTest.java @@ -38,10 +38,10 @@ void RegisterInterestCenter() { Center center = createCenter(); UUID volunteerId = UUID.fromString("123e4567-e89b-12d3-a456-426614174000"); UUID centerId = center.getId(); - RegisterInterestCenterRequestDto requestDto = new RegisterInterestCenterRequestDto(volunteerId, centerId); + RegisterInterestCenterRequestDto requestDto = new RegisterInterestCenterRequestDto(centerId); //when - RegisterInterestCenterResponseDto responseDto = registerInterestCenter.registerInterestCenter(requestDto); + RegisterInterestCenterResponseDto responseDto = registerInterestCenter.registerInterestCenter(volunteerId, requestDto); //then Optional result = interestCenterRepository.findInterestCenterResponseById(responseDto.id()); @@ -58,14 +58,14 @@ void registerInterestCenter_WithDuplicateCenterId_ShouldThrowException() { Center center = createCenter(); UUID volunteerId = UUID.fromString("123e4567-e89b-12d3-a456-426614174000"); UUID centerId = center.getId(); - RegisterInterestCenterRequestDto requestDto = new RegisterInterestCenterRequestDto(volunteerId, centerId); + RegisterInterestCenterRequestDto requestDto = new RegisterInterestCenterRequestDto(centerId); - registerInterestCenter.registerInterestCenter(requestDto); + registerInterestCenter.registerInterestCenter(volunteerId, requestDto); // when DuplicateException exception = assertThrows( DuplicateException.class, - () -> registerInterestCenter.registerInterestCenter(requestDto) + () -> registerInterestCenter.registerInterestCenter(volunteerId, requestDto) ); // then @@ -79,11 +79,11 @@ void registerInterestCenter_WithInvalidCenterId_ShouldThrowException() { // given UUID volunteerId = UUID.fromString("123e4567-e89b-12d3-a456-426614174000"); UUID invalidCenterId = UUID.fromString("123e4567-e89b-12d3-a456-426614174001"); - RegisterInterestCenterRequestDto requestDto = new RegisterInterestCenterRequestDto(volunteerId, invalidCenterId); + RegisterInterestCenterRequestDto requestDto = new RegisterInterestCenterRequestDto(invalidCenterId); // when BadRequestException exception = assertThrows(BadRequestException.class, () -> { - registerInterestCenter.registerInterestCenter(requestDto); + registerInterestCenter.registerInterestCenter(volunteerId, requestDto); }); //then