Skip to content

Commit

Permalink
refactor: Entity->DTO 변환 로직 정리, 페이지네이션 DTO 수정, 상세 DTO 생성
Browse files Browse the repository at this point in the history
  • Loading branch information
Ogu1208 committed Jul 20, 2024
1 parent c1f52dc commit d90f3c0
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import org.store.clothstar.category.service.CategoryService;
import org.store.clothstar.common.dto.MessageDTO;
import org.store.clothstar.common.util.URIBuilder;
import org.store.clothstar.productLine.dto.response.ProductLineWithProductsJPAResponse;
import org.store.clothstar.productLine.dto.response.ProductLineDetailResponse;
import org.store.clothstar.productLine.service.ProductLineService;

import java.net.URI;
Expand Down Expand Up @@ -68,21 +68,21 @@ public ResponseEntity<MessageDTO> updateCategories(

@Operation(summary = "카테고리별 상품 조회 (Offset Paging)", description = "카테고리 ID로 해당 카테고리에 속하는 모든 상품을 Offset Paging을 통해 조회한다.")
@GetMapping("/{categoryId}/productLines/offset")
public ResponseEntity<Page<ProductLineWithProductsJPAResponse>> getProductLinesByCategory(
public ResponseEntity<Page<ProductLineDetailResponse>> getProductLinesByCategory(
@PathVariable Long categoryId,
@PageableDefault(size = 18) Pageable pageable,
@RequestParam(required = false) String keyword) {
Page<ProductLineWithProductsJPAResponse> productLineResponses = productLineService.getProductLinesByCategoryWithOffsetPaging(categoryId, pageable, keyword);
Page<ProductLineDetailResponse> productLineResponses = productLineService.getProductLinesByCategoryWithOffsetPaging(categoryId, pageable, keyword);
return ResponseEntity.ok().body(productLineResponses);
}

@Operation(summary = "카테고리별 상품 조회 (Slice Paging)", description = "카테고리 ID로 해당 카테고리에 속하는 모든 상품을 Slice Paging을 통해 조회한다.")
@GetMapping("/{categoryId}/productLines/slice")
public ResponseEntity<Slice<ProductLineWithProductsJPAResponse>> getProductLinesByCategorySlice(
public ResponseEntity<Slice<ProductLineDetailResponse>> getProductLinesByCategorySlice(
@PathVariable Long categoryId,
@PageableDefault(size = 18) Pageable pageable,
@RequestParam(required = false) String keyword) {
Slice<ProductLineWithProductsJPAResponse> productLineResponses = productLineService.getProductLinesByCategoryWithSlicePaging(categoryId, pageable, keyword);
Slice<ProductLineDetailResponse> productLineResponses = productLineService.getProductLinesByCategoryWithSlicePaging(categoryId, pageable, keyword);
return ResponseEntity.ok().body(productLineResponses);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import org.store.clothstar.productLine.dto.request.CreateProductLineRequest;
import org.store.clothstar.productLine.dto.request.UpdateProductLineRequest;
import org.store.clothstar.productLine.dto.response.ProductLineResponse;
import org.store.clothstar.productLine.dto.response.ProductLineWithProductsJPAResponse;
import org.store.clothstar.productLine.dto.response.ProductLineDetailResponse;
import org.store.clothstar.productLine.service.ProductLineService;

import java.net.URI;
Expand All @@ -40,26 +40,26 @@ public ResponseEntity<List<ProductLineResponse>> getAllProductLines() {

@Operation(summary = "전체 상품 Offset Paging 조회", description = "삭제되지 않은 모든 상품을 조회한다.")
@GetMapping("/v1/productLines/offset")
public ResponseEntity<Page<ProductLineWithProductsJPAResponse>> getAllProductLinesOffsetPaging(
public ResponseEntity<Page<ProductLineDetailResponse>> getAllProductLinesOffsetPaging(
@PageableDefault(size = 18) Pageable pageable,
@RequestParam(required = false) String keyword){
Page<ProductLineWithProductsJPAResponse> productLineResponses = productLineService.getAllProductLinesWithProductsOffsetPaging(pageable, keyword);
Page<ProductLineDetailResponse> productLineResponses = productLineService.getAllProductLinesWithProductsOffsetPaging(pageable, keyword);
return ResponseEntity.ok().body(productLineResponses);
}

@Operation(summary = "전체 상품 Slice Paging 조회", description = "삭제되지 않은 모든 상품을 조회한다.")
@GetMapping("/v1/productLines/slice")
public ResponseEntity<Slice<ProductLineWithProductsJPAResponse>> getAllProductLinesSlicePaging(
public ResponseEntity<Slice<ProductLineDetailResponse>> getAllProductLinesSlicePaging(
@PageableDefault(size = 18) Pageable pageable,
@RequestParam(required = false) String keyword) {
Slice<ProductLineWithProductsJPAResponse> productLineResponses = productLineService.getAllProductLinesWithProductsSlicePaging(pageable, keyword);
Slice<ProductLineDetailResponse> productLineResponses = productLineService.getAllProductLinesWithProductsSlicePaging(pageable, keyword);
return ResponseEntity.ok().body(productLineResponses);
}

@Operation(summary = "상품 상세 조회", description = "productLineId로 상품과 하위 옵션들을 상세 조회한다.")
@GetMapping("/v1/productLines/{productLineId}")
public ResponseEntity<ProductLineWithProductsJPAResponse> getProductLine(@PathVariable("productLineId") Long productLineId) {
ProductLineWithProductsJPAResponse productLineWithProducts = productLineService.getProductLineWithProducts(productLineId);
public ResponseEntity<ProductLineDetailResponse> getProductLine(@PathVariable("productLineId") Long productLineId) {
ProductLineDetailResponse productLineWithProducts = productLineService.getProductLineWithProducts(productLineId);
return ResponseEntity.ok().body(productLineWithProducts);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,42 +1,77 @@
package org.store.clothstar.productLine.dto.response;

import lombok.Builder;
import lombok.Getter;
import org.store.clothstar.productLine.domain.ProductLine;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.querydsl.core.annotations.QueryProjection;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import org.store.clothstar.member.dto.response.SellerSimpleResponse;
import org.store.clothstar.product.dto.response.ProductResponse;
import org.store.clothstar.product.entity.ProductEntity;
import org.store.clothstar.productLine.domain.type.ProductLineStatus;
import org.store.clothstar.productLine.entity.ProductLineEntity;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Getter
@Builder
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class ProductLineDetailResponse {
private Long productId;

@Schema(description = "상품 id", example = "1")
private Long productLineId;

@Schema(description = "상품 이름", example = "우유 모자")
private String name;
private String brandName;

@Schema(description = "상품 설명", example = "우유 모자입니다.")
private String content;

@Schema(description = "상품 가격", example = "10000")
private int price;

@Schema(description = "상품 전체 재고", example = "100")
private Long totalStock;
private Long saleCount;
private ProductLineStatus productLineStatus;
private String biz_no;

@Schema(description = "상품 상태", example = "FOR_SALE")
private ProductLineStatus status;

@Schema(description = "상품 판매량", example = "10")
private Long saleCount; // ~개 판매중

@Builder.Default
@Schema(description = "상품 옵션")
private List<ProductResponse> productList = new ArrayList<>();

@Schema(description = "판매자 정보")
private SellerSimpleResponse seller;

@Schema(description = "생성일시")
@JsonSerialize(using = LocalDateTimeSerializer.class)
private LocalDateTime createdAt;

@Schema(description = "수정일시")
private LocalDateTime modifiedAt;
private LocalDateTime deletedAt;

public static ProductLineDetailResponse from(ProductLine productLine) {
return ProductLineDetailResponse.builder()
.productId(productLine.getProductLineId())
.name(productLine.getName())
.content(productLine.getContent())
.brandName(productLine.getBrandName())
.price(productLine.getPrice())
.totalStock(productLine.getTotalStock())
.saleCount(productLine.getSaleCount())
.productLineStatus(productLine.getStatus())
.biz_no(productLine.getBiz_no())
.createdAt(productLine.getCreatedAt())
.modifiedAt(productLine.getModifiedAt())
.deletedAt(productLine.getDeletedAt())
.build();

@QueryProjection
public ProductLineDetailResponse(ProductLineEntity productLine) {
this.productLineId = productLine.getProductLineId();
this.name = productLine.getName();
this.content = productLine.getContent();
this.price = productLine.getPrice();
this.totalStock = productLine.getProducts().stream().mapToLong(ProductEntity::getStock).sum();
this.status = productLine.getStatus();
this.saleCount = productLine.getSaleCount();
this.createdAt = productLine.getCreatedAt();
this.modifiedAt = productLine.getModifiedAt();
this.seller = SellerSimpleResponse.from(productLine.getSeller());
this.productList = productLine.getProducts().stream()
.map(ProductResponse::from)
.collect(Collectors.toList());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class ProductLineWithProductsJPAResponse {
public class ProductLinePaginationResponse {

@Schema(description = "상품 id", example = "1")
private Long productLineId;
Expand Down Expand Up @@ -58,7 +58,7 @@ public class ProductLineWithProductsJPAResponse {
private LocalDateTime modifiedAt;

@QueryProjection
public ProductLineWithProductsJPAResponse(ProductLineEntity productLine, Seller seller, Long totalStock) {
public ProductLinePaginationResponse(ProductLineEntity productLine, Seller seller, Long totalStock) {
this.productLineId = productLine.getProductLineId();
this.name = productLine.getName();
this.content = productLine.getContent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,11 @@
import org.store.clothstar.category.repository.CategoryJpaRepository;
import org.store.clothstar.member.domain.Seller;
import org.store.clothstar.member.repository.SellerRepository;
import org.store.clothstar.product.dto.response.ProductResponse;
import org.store.clothstar.product.entity.ProductEntity;
import org.store.clothstar.productLine.domain.type.ProductLineStatus;
import org.store.clothstar.productLine.dto.request.CreateProductLineRequest;
import org.store.clothstar.productLine.dto.request.UpdateProductLineRequest;
import org.store.clothstar.productLine.dto.response.ProductLineResponse;
import org.store.clothstar.productLine.dto.response.ProductLineWithProductsJPAResponse;
import org.store.clothstar.productLine.dto.response.ProductLineDetailResponse;
import org.store.clothstar.productLine.entity.ProductLineEntity;
import org.store.clothstar.productLine.repository.ProductLineJPARepository;

Expand All @@ -46,36 +44,36 @@ public List<ProductLineResponse> getAllProductLines() {
}

@Transactional(readOnly = true)
public Page<ProductLineWithProductsJPAResponse> getAllProductLinesWithProductsOffsetPaging(Pageable pageable, String keyword) {
public Page<ProductLineDetailResponse> getAllProductLinesWithProductsOffsetPaging(Pageable pageable, String keyword) {
Page<ProductLineEntity> allOffsetPaging = productLineRepository.findAllOffsetPaging(pageable, keyword);

return allOffsetPaging.map(this::convertToDtoWithProducts);
}

@Transactional(readOnly = true)
public Slice<ProductLineWithProductsJPAResponse> getAllProductLinesWithProductsSlicePaging(Pageable pageable, String keyword) {
public Slice<ProductLineDetailResponse> getAllProductLinesWithProductsSlicePaging(Pageable pageable, String keyword) {
Slice<ProductLineEntity> allSlicePaging = productLineRepository.findAllSlicePaging(pageable, keyword);
return allSlicePaging.map(this::convertToDtoWithProducts);
}

@Deprecated
@Transactional(readOnly = true)
public ProductLineWithProductsJPAResponse getProductLineWithProducts(Long productLineId) {
public ProductLineDetailResponse getProductLineWithProducts(Long productLineId) {
ProductLineEntity productLine = productLineRepository.findById(productLineId)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST, "상품 정보를 찾을 수 없습니다."));

return convertToDtoWithProducts(productLine);
}

@Transactional
public Page<ProductLineWithProductsJPAResponse> getProductLinesByCategoryWithOffsetPaging(Long categoryId, Pageable pageable, String keyword) {
public Page<ProductLineDetailResponse> getProductLinesByCategoryWithOffsetPaging(Long categoryId, Pageable pageable, String keyword) {
Page<ProductLineEntity> allOffsetPagingByCategory = productLineRepository.findEntitiesByCategoryWithOffsetPaging(categoryId, pageable, keyword);

return allOffsetPagingByCategory.map(this::convertToDtoWithProducts);
}

@Transactional
public Slice<ProductLineWithProductsJPAResponse> getProductLinesByCategoryWithSlicePaging(Long categoryId, Pageable pageable, String keyword) {
public Slice<ProductLineDetailResponse> getProductLinesByCategoryWithSlicePaging(Long categoryId, Pageable pageable, String keyword) {
Slice<ProductLineEntity> allSlicePagingByCategory = productLineRepository.findEntitiesByCategoryWithSlicePaging(categoryId, pageable, keyword);

return allSlicePagingByCategory.map(this::convertToDtoWithProducts);
Expand Down Expand Up @@ -112,24 +110,8 @@ public void setDeletedAt(Long productId) {
productLine.delete();
}

private ProductLineWithProductsJPAResponse convertToDtoWithProducts(ProductLineEntity productLine) {
// 전체 재고량 계산
Long totalStock = productLine.getProducts().stream().mapToLong(ProductEntity::getStock).sum();

// ProductLineWithProductsJPAResponse 객체 생성
ProductLineWithProductsJPAResponse dto = new ProductLineWithProductsJPAResponse(
productLine,
productLine.getSeller(),
totalStock
);

// productList 설정
List<ProductResponse> productResponses = productLine.getProducts().stream()
.map(ProductResponse::from)
.collect(Collectors.toList());
dto.setProductList(productResponses);

return dto;
private ProductLineDetailResponse convertToDtoWithProducts(ProductLineEntity productLine) {
return new ProductLineDetailResponse(productLine);
}

public List<ProductLineEntity> findByIdIn(List<Long> productLineIds) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.store.clothstar.productLine.service;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
Expand All @@ -16,7 +15,7 @@
import org.store.clothstar.productLine.dto.request.CreateProductLineRequest;
import org.store.clothstar.productLine.dto.request.UpdateProductLineRequest;
import org.store.clothstar.productLine.dto.response.ProductLineResponse;
import org.store.clothstar.productLine.dto.response.ProductLineWithProductsJPAResponse;
import org.store.clothstar.productLine.dto.response.ProductLineDetailResponse;
import org.store.clothstar.productLine.entity.ProductLineEntity;
import org.store.clothstar.productLine.repository.ProductLineJPARepository;

Expand Down Expand Up @@ -97,14 +96,14 @@ public void givenProductLines_whenGetProductLineList_thenGetProductLines() {
public void givenProductLineId_whenGetProductLineWithProducts_thenProductLineWithProducts() {
// given
Long productLineId = 1L;
ProductLineWithProductsJPAResponse mockResponse = mock(ProductLineWithProductsJPAResponse.class);
ProductLineDetailResponse mockResponse = mock(ProductLineDetailResponse.class);
when(mockResponse.getProductLineId()).thenReturn(productLineId);
when(mockResponse.getTotalStock()).thenReturn(90L);

given(productLineRepository.findProductLineWithOptionsById(productLineId)).willReturn(Optional.of(mockResponse));

// when
ProductLineWithProductsJPAResponse response = productLineService.getProductLineWithProducts(productLineId);
ProductLineDetailResponse response = productLineService.getProductLineWithProducts(productLineId);

// then
assertThat(response).isNotNull();
Expand Down

0 comments on commit d90f3c0

Please sign in to comment.