Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ dependencies {

//Junit
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

// querydsl
implementation "com.querydsl:querydsl-jpa:5.0.0:jakarta"
annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,28 @@ public ResponseEntity<ApiResult<String>> getAuctionStatus(@PathVariable Long auc
// return ResponseEntity.ok(ApiResult.success(ApiResponseMessages.AUCTION_BY_USER_RETRIEVED, userAuctions));
// }

@GetMapping
@Operation(summary = "Get all auctions", description = "Retrieves all auctions.")
@ApiResponse(responseCode = "200", description = "All auctions retrieved successfully")
public ResponseEntity<ApiResult<List<AuctionResponse>>> getAllAuctions(@RequestParam(required = false) AuctionRequest.AuctionCategoryParam auctionCategory) {
List<AuctionResponse> allAuctions;
if (auctionCategory != null) {
allAuctions = auctionService.getAuctionsByAuctionCategory(auctionCategory.getAuctionCategory());
} else {
allAuctions = auctionService.getAllAuctions();
}
return ResponseEntity.ok(ApiResult.success(ApiResponseMessages.ALL_AUCTIONS_RETRIEVED, allAuctions));
}
// @GetMapping
// @Operation(summary = "Get all auctions", description = "Retrieves all auctions.")
// @ApiResponse(responseCode = "200", description = "All auctions retrieved successfully")
// public ResponseEntity<ApiResult<List<AuctionResponse>>> getAllAuctions(@RequestParam(required = false) AuctionRequest.AuctionCategoryParam auctionCategory) {
// List<AuctionResponse> allAuctions;
// if (auctionCategory != null) {
// allAuctions = auctionService.getAuctionsByAuctionCategory(auctionCategory);
// } else {
// allAuctions = auctionService.getAllAuctions();
// }
// return ResponseEntity.ok(ApiResult.success(ApiResponseMessages.ALL_AUCTIONS_RETRIEVED, allAuctions));
// }
@GetMapping
@Operation(summary = "Get all auctions", description = "Retrieves all auctions.")
@ApiResponse(responseCode = "200", description = "All auctions retrieved successfully")
public ResponseEntity<ApiResult<List<AuctionResponse>>> getAllAuctions(
@RequestParam(required = false) AuctionRequest.AuctionCategoryParam auctionCategory,
@RequestParam(required = false) AuctionRequest.ProductCategoryParam productCategory
) {
List<AuctionResponse> auctions = auctionService.getAuctionsByFilter(productCategory,auctionCategory);
return ResponseEntity.ok(ApiResult.success(ApiResponseMessages.ALL_AUCTIONS_RETRIEVED, auctions));
}

@GetMapping("/{auctionId}")
@Operation(summary = "Get auction by ID", description = "Retrieves auction details by its ID.")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.tasksprints.auction.common.config;

import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QueryDslConfig {
@PersistenceContext
private EntityManager entityManager;

@Bean
public JPAQueryFactory jpaQueryFactory(){
return new JPAQueryFactory(entityManager);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.tasksprints.auction.domain.auction.model.AuctionCategory;
import com.tasksprints.auction.domain.auction.model.AuctionStatus;
import com.tasksprints.auction.domain.product.model.ProductCategory;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -26,7 +27,17 @@ public static class Create{
public static class AuctionCategoryParam {
AuctionCategory auctionCategory;
public AuctionCategoryParam(String auctionCategory){
this.auctionCategory = AuctionCategory.fromString(auctionCategory);
this.auctionCategory = AuctionCategory.fromDisplayName(auctionCategory);
}
}

@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class ProductCategoryParam {
ProductCategory productCategory;
public ProductCategoryParam(String productCategory){
this.productCategory = ProductCategory.fromDisplayName(productCategory);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ public enum AuctionCategory {
PRIVATE_PAID,
PUBLIC_PAID;

public static AuctionCategory fromString(String auctionCategory) {
public static AuctionCategory fromDisplayName(String auctionCategory) {
try {
return AuctionCategory.valueOf(auctionCategory.toUpperCase()); // 대문자로 변환하여 비교
} catch (IllegalArgumentException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.tasksprints.auction.domain.auction.repository;

import com.tasksprints.auction.domain.auction.model.Auction;
import com.tasksprints.auction.domain.auction.model.AuctionCategory;
import com.tasksprints.auction.domain.product.model.ProductCategory;


import java.util.List;

public interface AuctionCriteriaRepository {
public List<Auction> getAuctionsByFilters(ProductCategory productCategory,
AuctionCategory category);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.tasksprints.auction.domain.auction.repository;

import com.querydsl.jpa.impl.JPAQueryFactory;
import com.tasksprints.auction.domain.auction.model.Auction;
import com.tasksprints.auction.domain.auction.model.AuctionCategory;
import com.tasksprints.auction.domain.auction.model.QAuction;
import com.tasksprints.auction.domain.product.model.ProductCategory;
import com.tasksprints.auction.domain.product.model.QProduct;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

import java.util.List;

@RequiredArgsConstructor
@Repository
public class AuctionCriteriaRepositoryImpl implements AuctionCriteriaRepository {
private final JPAQueryFactory queryFactory;
public List<Auction> getAuctionsByFilters( ProductCategory productCategory,
AuctionCategory category
) {
QAuction auction = QAuction.auction;
QProduct product = QProduct.product;
return queryFactory.selectFrom(auction)
.leftJoin(auction.product, product) // Auction과 Product 조인
.where(category != null ? auction.auctionCategory.eq(category) : null)
.where(productCategory != null ? product.category.eq(productCategory) : null) // ProductCategory 필터
.fetch();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@

import com.tasksprints.auction.domain.auction.model.Auction;
import com.tasksprints.auction.domain.auction.model.AuctionCategory;
import com.tasksprints.auction.domain.product.model.ProductCategory;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;
import java.util.Optional;

public interface AuctionRepository extends JpaRepository<Auction, Long> {
public interface AuctionRepository extends JpaRepository<Auction, Long>,AuctionCriteriaRepository{


@Query("SELECT a FROM auction a WHERE a.seller.id = :userId")
Expand All @@ -20,5 +21,6 @@ public interface AuctionRepository extends JpaRepository<Auction, Long> {
Optional<Auction> findAuctionById(@Param("auctionId") Long auctionId);

List<Auction> findAuctionsByAuctionCategory(AuctionCategory auctionCategory);
List<Auction> findAuctionByProduct_Category(ProductCategory productCategory);
}

Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@
*/
public interface AuctionService {
AuctionResponse createAuction(Long userId, AuctionRequest.Create auctionRequest);

void closeAuction(Long auctionId);
String getAuctionStatus(Long auctionId);
List<AuctionResponse> getAuctionsByUser(Long userId);
List<AuctionResponse> getAuctionsByProductCategory(AuctionRequest.ProductCategoryParam param);
List<AuctionResponse> getAllAuctions();
AuctionResponse getAuctionById(Long auctionId);
List<AuctionResponse> getAuctionsByAuctionCategory(AuctionCategory auctionCategory);
List<AuctionResponse> getAuctionsByAuctionCategory(AuctionRequest.AuctionCategoryParam param);
List<AuctionResponse> getAuctionsByFilter(AuctionRequest.ProductCategoryParam productCategoryParam, AuctionRequest.AuctionCategoryParam auctionCategoryParam);
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ public List<AuctionResponse> getAuctionsByUser(Long userId) {
.toList();
}


@Override
public List<AuctionResponse> getAllAuctions() {
List<Auction> foundAuctions = auctionRepository.findAll();
Expand All @@ -101,10 +102,34 @@ public AuctionResponse getAuctionById(Long auctionId) {

return AuctionResponse.of(foundAuction);
}
@Deprecated
@Override
public List<AuctionResponse> getAuctionsByProductCategory(AuctionRequest.ProductCategoryParam param) {
List<Auction> foundAuctions = auctionRepository.findAuctionByProduct_Category(param.getProductCategory());

return foundAuctions.stream()
.map(AuctionResponse::of)
.toList();

}

@Deprecated
@Override
public List<AuctionResponse> getAuctionsByAuctionCategory(AuctionRequest.AuctionCategoryParam param) {
List<Auction> foundAuctions = auctionRepository.findAuctionsByAuctionCategory(param.getAuctionCategory());

return foundAuctions.stream()
.map(AuctionResponse::of)
.toList();
}
/**
* NULL POINTER EXCEPTION 발생
* NULL 안정성 보장을 해줬음**/
@Override
public List<AuctionResponse> getAuctionsByAuctionCategory(AuctionCategory auctionCategory) {
List<Auction> foundAuctions = auctionRepository.findAuctionsByAuctionCategory(auctionCategory);
public List<AuctionResponse> getAuctionsByFilter(AuctionRequest.ProductCategoryParam productCategoryParam, AuctionRequest.AuctionCategoryParam auctionCategoryParam) {
List<Auction> foundAuctions = auctionRepository.getAuctionsByFilters(
productCategoryParam!=null?productCategoryParam.getProductCategory():null,
auctionCategoryParam!=null?auctionCategoryParam.getAuctionCategory():null);

return foundAuctions.stream()
.map(AuctionResponse::of)
Expand Down
5 changes: 4 additions & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ springdoc:
display-request-duration: true
operations-sorter: alpha
packages-to-scan: com.tasksprints.auction.api

logging:
level:
org.hibernate.SQL: DEBUG
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
server:
port: 8080

Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ public void testGetAuctionStatus_Success() throws Exception {
@DisplayName("경매 유형을 통한 경매목록 조회")
public void testFindAuctionByUsingAuctionCategory_Success() throws Exception {
List<AuctionResponse> auctionResponseList = new ArrayList<>();
when(auctionService.getAuctionsByAuctionCategory(any())).thenReturn(auctionResponseList);
when(auctionService.getAuctionsByFilter(any(),any())).thenReturn(auctionResponseList);
mockMvc.perform(get("/api/v1/auction")
.param("auctionCategory", String.valueOf(AuctionCategory.PRIVATE_FREE)))
.andExpect(status().isOk())
Expand All @@ -125,7 +125,7 @@ public void testFindAuctionByUsingAuctionCategory_Success() throws Exception {
@DisplayName("잘못된 유형을 통한 경매목록 조회(기본값으로 대응)")
public void testFindAuctionByUsingWrongAuctionCategory_Success() throws Exception {
List<AuctionResponse> auctionResponseList = new ArrayList<>();
when(auctionService.getAuctionsByAuctionCategory(any())).thenReturn(auctionResponseList);
when(auctionService.getAuctionsByFilter(any(),any())).thenReturn(auctionResponseList);

mockMvc.perform(get("/api/v1/auction")
.param("auctionCategory", "NON"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package com.tasksprints.auction.domain.auction.repository;
import com.tasksprints.auction.common.config.QueryDslConfig;
import com.tasksprints.auction.domain.auction.model.Auction;
import com.tasksprints.auction.domain.auction.model.AuctionCategory;
import com.tasksprints.auction.domain.auction.model.AuctionStatus;
Expand All @@ -11,6 +12,7 @@
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.context.annotation.Import;

import java.math.BigDecimal;
import java.time.LocalDateTime;
Expand All @@ -21,6 +23,7 @@
import static org.junit.jupiter.api.Assertions.assertTrue;

@DataJpaTest
@Import(QueryDslConfig.class)
@Slf4j
public class AuctionRepositoryTest {

Expand Down Expand Up @@ -101,7 +104,24 @@ public void testFindAuctionsByAuctionCategory() {
assertThat(auctions).hasSize(2);
assertThat(auctions).allMatch(auction -> auction.getAuctionCategory() == AuctionCategory.PUBLIC_PAID);
}
@Test
@DisplayName("QueryDSL 필터를 통해서 경매 목록 조회")
public void testFindAllUsingFilter() {
Auction auction1 = createAuction(seller, AuctionCategory.PUBLIC_FREE, AuctionStatus.ACTIVE);
Auction auction2 = createAuction(seller, AuctionCategory.PUBLIC_PAID, AuctionStatus.PENDING);

auctionRepository.save(auction1);
auctionRepository.save(auction2);

List<Auction> auctions = auctionRepository.getAuctionsByFilters(null, AuctionCategory.PUBLIC_FREE);
log.info(auctions.toString());

assertThat(auctions).hasSize(1);
assertThat(auctions.get(0).getAuctionCategory()).isEqualTo(AuctionCategory.PUBLIC_FREE);
assertThat(auctions.get(0).getAuctionCategory()).isNotEqualTo(AuctionCategory.PUBLIC_PAID);


}
private Auction createAuction(User seller, AuctionCategory category, AuctionStatus status) {
return Auction.create(
LocalDateTime.now(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,36 +297,58 @@ class GetAuctionsByAuctionCategoryTests {
public void testGetAuctionsByAuctionCategory_Success() {
Auction auction1 = createAuction(1L, seller, AuctionStatus.PENDING);
Auction auction2 = createAuction(2L, seller, AuctionStatus.PENDING);

AuctionRequest.AuctionCategoryParam param = new AuctionRequest.AuctionCategoryParam(AuctionCategory.PUBLIC_PAID);
List<Auction> expectedAuctions = List.of(auction1, auction2);

when(auctionRepository.findAuctionsByAuctionCategory(AuctionCategory.PUBLIC_PAID)).thenReturn(expectedAuctions);
List<AuctionResponse> expectedResponses = expectedAuctions.stream()
.map(AuctionResponse::of)
.collect(Collectors.toList());

List<AuctionResponse> actualAuctions = auctionService.getAuctionsByAuctionCategory(AuctionCategory.PUBLIC_PAID);
List<AuctionResponse> actualAuctions = auctionService.getAuctionsByAuctionCategory(param);
assertThat(actualAuctions).isEqualTo(expectedResponses);
}
@Test
@DisplayName("경매 유형 조회 : [성공] -Criteria 사용")
public void testGetAuctionsByAuctionCategory_Success_Criteria() {
Auction auction1 = createAuction(1L, seller, AuctionStatus.PENDING);
Auction auction2 = createAuction(2L, seller, AuctionStatus.PENDING);
AuctionRequest.AuctionCategoryParam param = new AuctionRequest.AuctionCategoryParam(AuctionCategory.PUBLIC_PAID);
List<Auction> expectedAuctions = List.of(auction1, auction2);

when(auctionRepository.getAuctionsByFilters(null,AuctionCategory.PUBLIC_PAID)).thenReturn(expectedAuctions);
List<AuctionResponse> expectedResponses = expectedAuctions.stream()
.map(AuctionResponse::of)
.toList();

List<AuctionResponse> actualAuctions = auctionService.getAuctionsByFilter(null,param);
assertThat(actualAuctions).isEqualTo(expectedResponses);
}
@Test
@DisplayName("경매 유형 조회 : [결과 없음]")
public void testGetAuctionsByAuctionCategory_AuctionNotFound() {
List<Auction> emptyAuctionList = List.of();
AuctionRequest.AuctionCategoryParam param = new AuctionRequest.AuctionCategoryParam(AuctionCategory.PUBLIC_FREE);

when(auctionRepository.findAuctionsByAuctionCategory(AuctionCategory.PUBLIC_FREE))
.thenReturn(emptyAuctionList);

List<AuctionResponse> actualAuctions = auctionService.getAuctionsByAuctionCategory(AuctionCategory.PUBLIC_FREE);
List<AuctionResponse> actualAuctions = auctionService.getAuctionsByAuctionCategory(param);

assertThat(actualAuctions).isEmpty();
}
@Test
@DisplayName("경매 유형 조회 : [결과 없음] - Criteria 사용")
public void testGetAuctionsByAuctionCategory_AuctionNotFound_Criteria() {
List<Auction> emptyAuctionList = List.of();
AuctionRequest.AuctionCategoryParam param = new AuctionRequest.AuctionCategoryParam(AuctionCategory.PUBLIC_FREE);

//service 메서드 안에서 예외 처리를 하면 아래 코드로 테스트?
// assertThrows(AuctionNotFoundException.class, () -> {
// auctionService.getAuctionsByAuctionCategory(AuctionCategory.PUBLIC_FREE);
// });

when(auctionRepository.getAuctionsByFilters(null,AuctionCategory.PUBLIC_FREE))
.thenReturn(emptyAuctionList);

List<AuctionResponse> actualAuctions = auctionService.getAuctionsByFilter(null,param);

assertThat(actualAuctions).isEmpty();
}
}

Expand Down
Loading