diff --git a/src/main/java/com/ajou/hertz/domain/instrument/repository/InstrumentRepository.java b/src/main/java/com/ajou/hertz/domain/instrument/repository/InstrumentRepository.java index 3677057..32c6be4 100644 --- a/src/main/java/com/ajou/hertz/domain/instrument/repository/InstrumentRepository.java +++ b/src/main/java/com/ajou/hertz/domain/instrument/repository/InstrumentRepository.java @@ -2,7 +2,11 @@ import org.springframework.data.jpa.repository.JpaRepository; +import com.ajou.hertz.domain.instrument.constant.InstrumentProgressStatus; import com.ajou.hertz.domain.instrument.entity.Instrument; public interface InstrumentRepository extends JpaRepository, InstrumentRepositoryCustom { + + int countBySellerIdAndProgressStatus(Long sellerid, InstrumentProgressStatus progressStatus); + } diff --git a/src/main/java/com/ajou/hertz/domain/instrument/service/InstrumentQueryService.java b/src/main/java/com/ajou/hertz/domain/instrument/service/InstrumentQueryService.java index 3bc8677..db5f358 100644 --- a/src/main/java/com/ajou/hertz/domain/instrument/service/InstrumentQueryService.java +++ b/src/main/java/com/ajou/hertz/domain/instrument/service/InstrumentQueryService.java @@ -13,6 +13,7 @@ import com.ajou.hertz.domain.instrument.audio_equipment.dto.request.AudioEquipmentFilterConditions; import com.ajou.hertz.domain.instrument.bass_guitar.dto.BassGuitarDto; import com.ajou.hertz.domain.instrument.bass_guitar.dto.request.BassGuitarFilterConditions; +import com.ajou.hertz.domain.instrument.constant.InstrumentProgressStatus; import com.ajou.hertz.domain.instrument.constant.InstrumentSortOption; import com.ajou.hertz.domain.instrument.dto.InstrumentDto; import com.ajou.hertz.domain.instrument.effector.dto.EffectorDto; @@ -194,4 +195,25 @@ public Page findAudioEquipmentDtos( .findAudioEquipments(page, pageSize, sort, filterConditions) .map(InstrumentMapper::toAmplifierDto); } + + /** + * 판매자가 판매중인 물품의 수를 조회합니다 + * + * @param sellerId 판매자 id + * + * @return 판매중인 물품의 수 + */ + public int countSellingItemsBySellerId(Long sellerId) { + return instrumentRepository.countBySellerIdAndProgressStatus(sellerId, InstrumentProgressStatus.SELLING); + } + + /** + * 판매자가 판매완료한 물품의 수를 조회한다 + * + * @param sellerId 판매자 id + * @return 판매완료한 물품의 수 + */ + public int countSoldItemsBySellerId(Long sellerId) { + return instrumentRepository.countBySellerIdAndProgressStatus(sellerId, InstrumentProgressStatus.SOLD_OUT); + } } diff --git a/src/main/java/com/ajou/hertz/domain/user/controller/UserController.java b/src/main/java/com/ajou/hertz/domain/user/controller/UserController.java index 70496a1..8d584ab 100644 --- a/src/main/java/com/ajou/hertz/domain/user/controller/UserController.java +++ b/src/main/java/com/ajou/hertz/domain/user/controller/UserController.java @@ -9,6 +9,7 @@ import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -20,10 +21,12 @@ import com.ajou.hertz.common.auth.UserPrincipal; import com.ajou.hertz.common.validator.PhoneNumber; +import com.ajou.hertz.domain.instrument.service.InstrumentQueryService; import com.ajou.hertz.domain.user.dto.UserDto; import com.ajou.hertz.domain.user.dto.request.SignUpRequest; import com.ajou.hertz.domain.user.dto.request.UpdateContactLinkRequest; import com.ajou.hertz.domain.user.dto.request.UpdatePasswordRequest; +import com.ajou.hertz.domain.user.dto.response.SellerInfoResponse; import com.ajou.hertz.domain.user.dto.response.UserEmailResponse; import com.ajou.hertz.domain.user.dto.response.UserExistenceResponse; import com.ajou.hertz.domain.user.dto.response.UserResponse; @@ -52,6 +55,7 @@ public class UserController { private final UserCommandService userCommandService; private final UserQueryService userQueryService; + private final InstrumentQueryService instrumentQueryService; @Operation( summary = "내 정보 조회", @@ -171,5 +175,20 @@ public UserResponse updatePasswordV1( return UserResponse.from(userUpdated); } + @Operation( + summary = "판매자 정보 조회", + description = "판매자 정보(유저 정보 + 판매 중인 매물 수 + 판매 완료 매물 수)를 조회합니다.", + security = @SecurityRequirement(name = "access-token") + ) + @GetMapping(value = "/{userId}/seller", headers = API_VERSION_HEADER_NAME + "=" + 1) + public SellerInfoResponse getSellerInfoV1( + @PathVariable Long userId + ) { + UserDto userDto = userQueryService.getDtoById(userId); + int sellingCount = instrumentQueryService.countSellingItemsBySellerId(userId); + int soldCount = instrumentQueryService.countSoldItemsBySellerId(userId); + return SellerInfoResponse.from(userDto, sellingCount, soldCount); + } + } diff --git a/src/main/java/com/ajou/hertz/domain/user/dto/response/SellerInfoResponse.java b/src/main/java/com/ajou/hertz/domain/user/dto/response/SellerInfoResponse.java new file mode 100644 index 0000000..a240cff --- /dev/null +++ b/src/main/java/com/ajou/hertz/domain/user/dto/response/SellerInfoResponse.java @@ -0,0 +1,50 @@ +package com.ajou.hertz.domain.user.dto.response; + +import java.time.LocalDateTime; + +import com.ajou.hertz.domain.user.dto.UserDto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor(access = AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +public class SellerInfoResponse { + + @Schema(description = "Id of user", example = "1") + private Long id; + + @Schema(description = "이메일", example = "test@gmail.com") + private String email; + + @Schema(description = "프로필 이미지 url", example = "https://user-profile-image") + private String profileImage; + + @Schema(description = "연락 수단", example = "https://contack-link") + private String contactLink; + + @Schema(description = "가입일", example = "2024.01.01") + private LocalDateTime createdAt; + + @Schema(description = "판매중인 물품의 수", example = "10") + private long sellingItemCount; + + @Schema(description = "판매완료한 물품의 수", example = "10") + private long soldItemCount; + + public static SellerInfoResponse from(UserDto userDto, long sellingItemCount, long soldItemCount) { + return new SellerInfoResponse( + userDto.getId(), + userDto.getEmail(), + userDto.getProfileImageUrl(), + userDto.getContactLink(), + userDto.getCreatedAt(), + sellingItemCount, + soldItemCount + ); + } +} diff --git a/src/test/java/com/ajou/hertz/unit/domain/instrument/service/InstrumentQueryServiceTest.java b/src/test/java/com/ajou/hertz/unit/domain/instrument/service/InstrumentQueryServiceTest.java index 047b669..fc0ffd9 100644 --- a/src/test/java/com/ajou/hertz/unit/domain/instrument/service/InstrumentQueryServiceTest.java +++ b/src/test/java/com/ajou/hertz/unit/domain/instrument/service/InstrumentQueryServiceTest.java @@ -363,6 +363,44 @@ class InstrumentQueryServiceTest { ); } + @Test + void 해당_유저의_판매_중인_물품의_수를_조회한다() throws Exception { + // given + Long sellerId = 1L; + int expectedResult = 3; + given(instrumentRepository.countBySellerIdAndProgressStatus(sellerId, InstrumentProgressStatus.SELLING)) + .willReturn(expectedResult); + + // when + int actualResult = sut.countSellingItemsBySellerId(sellerId); + + // then + assertThat(actualResult).isEqualTo(expectedResult); + then(instrumentRepository).should() + .countBySellerIdAndProgressStatus(sellerId, InstrumentProgressStatus.SELLING); + verifyEveryMocksShouldHaveNoMoreInteractions(); + assertThat(actualResult).isEqualTo(expectedResult); + } + + @Test + void 해당_유저의_판매_완료한한물품의_수를_조회한다() throws Exception { + // given + Long sellerId = 1L; + int expectedResult = 3; + given(instrumentRepository.countBySellerIdAndProgressStatus(sellerId, InstrumentProgressStatus.SOLD_OUT)) + .willReturn(expectedResult); + + // when + int actualResult = sut.countSoldItemsBySellerId(sellerId); + + // then + assertThat(actualResult).isEqualTo(expectedResult); + then(instrumentRepository).should() + .countBySellerIdAndProgressStatus(sellerId, InstrumentProgressStatus.SOLD_OUT); + verifyEveryMocksShouldHaveNoMoreInteractions(); + assertThat(actualResult).isEqualTo(expectedResult); + } + private void verifyEveryMocksShouldHaveNoMoreInteractions() { then(instrumentRepository).shouldHaveNoMoreInteractions(); } diff --git a/src/test/java/com/ajou/hertz/unit/domain/user/controller/UserControllerTest.java b/src/test/java/com/ajou/hertz/unit/domain/user/controller/UserControllerTest.java index 6595538..4c2cbe2 100644 --- a/src/test/java/com/ajou/hertz/unit/domain/user/controller/UserControllerTest.java +++ b/src/test/java/com/ajou/hertz/unit/domain/user/controller/UserControllerTest.java @@ -31,6 +31,7 @@ import com.ajou.hertz.common.auth.JwtTokenProvider; import com.ajou.hertz.common.auth.UserPrincipal; import com.ajou.hertz.common.config.SecurityConfig; +import com.ajou.hertz.domain.instrument.service.InstrumentQueryService; import com.ajou.hertz.domain.user.constant.Gender; import com.ajou.hertz.domain.user.constant.RoleType; import com.ajou.hertz.domain.user.controller.UserController; @@ -61,6 +62,9 @@ class UserControllerTest { @MockBean private UserQueryService userQueryService; + @MockBean + private InstrumentQueryService instrumentQueryService; + private final MockMvc mvc; private final ObjectMapper objectMapper; @@ -295,6 +299,31 @@ public void securitySetUp() throws Exception { verifyEveryMocksShouldHaveNoMoreInteractions(); } + @Test + void 주어진_id로_판매자의_판매자_정보를_조회한다() throws Exception { + // given + long userId = 1L; + UserDetails testUser = createTestUser(userId); + UserDto expectedResult = createUserDto(userId); + int sellingCount = 2; + int soldCount = 3; + given(userQueryService.getDtoById(userId)).willReturn(expectedResult); + given(instrumentQueryService.countSellingItemsBySellerId(userId)).willReturn(sellingCount); + given(instrumentQueryService.countSoldItemsBySellerId(userId)).willReturn(soldCount); + + // when & then + mvc.perform( + get("/api/users/{userId}/seller", userId) + .header(API_VERSION_HEADER_NAME, 1) + .with(user(testUser)) + ) + .andExpect(status().isOk()); + then(userQueryService).should().getDtoById(userId); + then(instrumentQueryService).should().countSellingItemsBySellerId(userId); + then(instrumentQueryService).should().countSoldItemsBySellerId(userId); + verifyEveryMocksShouldHaveNoMoreInteractions(); + } + private void verifyEveryMocksShouldHaveNoMoreInteractions() { then(userCommandService).shouldHaveNoMoreInteractions(); then(userQueryService).shouldHaveNoMoreInteractions();