diff --git a/market-api/src/main/java/com/server/market/domain/product/dto/ProductPagingSimpleResponse.java b/market-api/src/main/java/com/server/market/domain/product/dto/ProductPagingSimpleResponse.java index 11953d2..42570c8 100644 --- a/market-api/src/main/java/com/server/market/domain/product/dto/ProductPagingSimpleResponse.java +++ b/market-api/src/main/java/com/server/market/domain/product/dto/ProductPagingSimpleResponse.java @@ -7,6 +7,8 @@ public record ProductPagingSimpleResponse( Long id, + Long thumbnailId, + String thumbnailUrl, String location, String title, Integer price, @@ -21,6 +23,8 @@ public record ProductPagingSimpleResponse( ) { public ProductPagingSimpleResponse( final Long id, + final Long thumbnailId, + final String thumbnailUrl, final Location location, final String title, final Integer price, @@ -33,6 +37,6 @@ public ProductPagingSimpleResponse( final Boolean isAlreadyLikedByMe, final LocalDateTime createDate ) { - this(id, location.getContent(), title, price, visitedCount, contactCount, productStatus, ownerId, ownerName, productLikesCount, isAlreadyLikedByMe, createDate); + this(id, thumbnailId, thumbnailUrl, location.getContent(), title, price, visitedCount, contactCount, productStatus, ownerId, ownerName, productLikesCount, isAlreadyLikedByMe, createDate); } } diff --git a/market-api/src/main/java/com/server/market/infrastructure/product/ProductQueryRepository.java b/market-api/src/main/java/com/server/market/infrastructure/product/ProductQueryRepository.java index 69bdb88..1f8755b 100644 --- a/market-api/src/main/java/com/server/market/infrastructure/product/ProductQueryRepository.java +++ b/market-api/src/main/java/com/server/market/infrastructure/product/ProductQueryRepository.java @@ -1,11 +1,16 @@ package com.server.market.infrastructure.product; +import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.CaseBuilder; import com.querydsl.jpa.impl.JPAQueryFactory; +import com.server.market.domain.product.QProduct; +import com.server.market.domain.product.QProductImage; +import com.server.market.domain.product.QProductLike; import com.server.market.domain.product.dto.ProductImageResponse; import com.server.market.domain.product.dto.ProductPagingSimpleResponse; import com.server.market.domain.product.dto.ProductSpecificResponse; +import com.server.member.domain.member.QMember; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; @@ -13,6 +18,7 @@ import java.util.Optional; import static com.querydsl.core.types.Projections.constructor; +import static com.querydsl.core.types.dsl.Expressions.stringTemplate; import static com.server.market.domain.category.QCategory.category; import static com.server.market.domain.product.QProduct.product; import static com.server.market.domain.product.QProductImage.productImage; @@ -26,8 +32,23 @@ public class ProductQueryRepository { private final JPAQueryFactory jpaQueryFactory; public List findAllWithPagingByCategoryId(final Long memberId, final Long productId, final Long categoryId, final int pageSize) { - return jpaQueryFactory.select(constructor(ProductPagingSimpleResponse.class, + QProduct product = QProduct.product; + QProductImage productImage = QProductImage.productImage; + QMember member = QMember.member; + QProductLike productLike = QProductLike.productLike; + + return jpaQueryFactory.select(Projections.constructor(ProductPagingSimpleResponse.class, product.id, + new CaseBuilder() + .when(productImage.id.isNull()) + .then(-1L) + .otherwise(productImage.id).as("imageId"), + new CaseBuilder() + .when(productImage.uniqueName.isNull()) + .then("null") + .otherwise( + stringTemplate("CONCAT('https://atwozimage.s3.ap-northeast-2.amazonaws.com/', {0})", productImage.uniqueName) + ).as("uniqueName"), product.description.location, product.description.title, product.price.price, @@ -39,13 +60,16 @@ public List findAllWithPagingByCategoryId(final Lon product.statisticCount.likedCount, isLikedAlreadyByMe(memberId), product.createdAt - )).from(product) - .where( - ltProductId(productId), - product.categoryId.eq(categoryId) - ).orderBy(product.id.desc()) + )) + .from(product) .leftJoin(member).on(product.memberId.eq(member.id)) .leftJoin(productLike).on(productLike.productId.eq(product.id).and(productLike.memberId.eq(memberId))) + .leftJoin(productImage).on(productImage.product.id.eq(product.id)) + .where( + ltProductId(productId), + categoryId != null ? product.categoryId.eq(categoryId) : product.categoryId.isNull() + ) + .orderBy(product.id.desc()) .limit(pageSize) .fetch(); } diff --git a/market-api/src/test/java/com/server/market/fixture/ProductFixture.java b/market-api/src/test/java/com/server/market/fixture/ProductFixture.java index 31c7b34..77db41c 100644 --- a/market-api/src/test/java/com/server/market/fixture/ProductFixture.java +++ b/market-api/src/test/java/com/server/market/fixture/ProductFixture.java @@ -42,7 +42,7 @@ public class ProductFixture { } public static ProductPagingSimpleResponse 상품_페이징_생성() { - return new ProductPagingSimpleResponse(1L, Location.BUILDING_CENTER, "상품명", 10000, 10, 2, ProductStatus.WAITING, 1L, "귀여운_피그미123", 3, true, LocalDateTime.now()); + return new ProductPagingSimpleResponse(1L, 1L, "url", Location.BUILDING_CENTER, "상품명", 10000, 10, 2, ProductStatus.WAITING, 1L, "귀여운_피그미123", 3, true, LocalDateTime.now()); } public static ProductSpecificResponse 상품_상세정보_생성() { diff --git a/market-api/src/test/java/com/server/market/infrastructure/product/ProductFakeRepository.java b/market-api/src/test/java/com/server/market/infrastructure/product/ProductFakeRepository.java index db8ce27..3df1c12 100644 --- a/market-api/src/test/java/com/server/market/infrastructure/product/ProductFakeRepository.java +++ b/market-api/src/test/java/com/server/market/infrastructure/product/ProductFakeRepository.java @@ -1,6 +1,5 @@ package com.server.market.infrastructure.product; -import com.server.market.domain.category.CategoryName; import com.server.market.domain.product.Product; import com.server.market.domain.product.ProductLike; import com.server.market.domain.product.ProductRepository; @@ -125,6 +124,8 @@ public List findImages(final Long productId) { private static ProductPagingSimpleResponse parse(final Product product) { return new ProductPagingSimpleResponse( product.getId(), + 1L, + "url", Location.BUILDING_CENTER, product.getDescription().getTitle(), product.getPrice().getPrice(), diff --git a/market-api/src/test/java/com/server/market/ui/product/ProductControllerWebMvcTest.java b/market-api/src/test/java/com/server/market/ui/product/ProductControllerWebMvcTest.java index a31242e..519626e 100644 --- a/market-api/src/test/java/com/server/market/ui/product/ProductControllerWebMvcTest.java +++ b/market-api/src/test/java/com/server/market/ui/product/ProductControllerWebMvcTest.java @@ -98,6 +98,8 @@ class ProductControllerWebMvcTest extends MockBeanInjection { ), responseFields( fieldWithPath("[].id").description("상품 id"), + fieldWithPath("[].thumbnailId").description("상품 id"), + fieldWithPath("[].thumbnailUrl").description("상품 id"), fieldWithPath("[].location").description("거래 장소 (3공학관, 5공학관 등등..)"), fieldWithPath("[].title").description("상품 제목"), fieldWithPath("[].price").description("상품 가격"), @@ -332,6 +334,8 @@ class ProductControllerWebMvcTest extends MockBeanInjection { Long categoryId = 1L; List response = List.of(new ProductPagingSimpleResponse( 1L, + 1L, + "url", "5공학관", "상품제목", 1000, @@ -359,6 +363,8 @@ class ProductControllerWebMvcTest extends MockBeanInjection { ), responseFields( fieldWithPath("[].id").description("상품 id"), + fieldWithPath("[].thumbnailId").description("상품 id"), + fieldWithPath("[].thumbnailUrl").description("상품 id"), fieldWithPath("[].location").description("거래 장소 (3공학관, 5공학관 등등..)"), fieldWithPath("[].title").description("상품 제목"), fieldWithPath("[].price").description("상품 가격"),