11package com .backend .domain .product .controller ;
22
3- import com .backend .domain .member .entity .Member ;
4- import com .backend .domain .member .service .MemberService ;
5- import com .backend .domain .product .document .ProductDocument ;
63import com .backend .domain .product .dto .ProductSearchDto ;
74import com .backend .domain .product .dto .request .ProductCreateRequest ;
85import com .backend .domain .product .dto .request .ProductModifyRequest ;
96import com .backend .domain .product .dto .response .*;
10- import com .backend .domain .product .entity .Product ;
117import com .backend .domain .product .enums .AuctionStatus ;
128import com .backend .domain .product .enums .ProductSearchSortType ;
139import com .backend .domain .product .enums .SaleStatus ;
14- import com .backend .domain .product .exception .ProductException ;
15- import com .backend .domain .product .mapper .ProductMapper ;
16- import com .backend .domain .product .service .ProductSearchService ;
17- import com .backend .domain .product .service .ProductService ;
10+ import com .backend .domain .product .facade .ProductFacade ;
1811import com .backend .global .page .dto .PageDto ;
1912import com .backend .global .response .RsData ;
2013import jakarta .validation .Valid ;
2114import lombok .RequiredArgsConstructor ;
22- import org .springframework .data .domain .Page ;
2315import org .springframework .http .MediaType ;
2416import org .springframework .security .core .annotation .AuthenticationPrincipal ;
2517import org .springframework .security .core .userdetails .User ;
2921
3022import java .util .List ;
3123
32- /**
33- * 상품 관련 REST API 컨트롤러
34- * - 경매 상품의 CRUD 작업을 처리
35- * - RDB와 Elasticsearch 기반 검색 기능 제공
36- * - 멀티파트 파일 업로드를 통한 이미지 처리
37- */
3824@ RestController
3925@ RequiredArgsConstructor
4026public class ApiV1ProductController implements ApiV1ProductControllerDocs {
41- private final ProductService productService ;
42- private final MemberService memberService ;
43- private final ProductMapper productMapper ;
44- private final ProductSearchService productSearchService ;
27+ private final ProductFacade productFacade ;
4528
46- /**
47- * 상품 등록
48- * - 상품 정보와 이미지를 함께 업로드하여 새 경매 상품 생성
49- * - 이미지는 최소 1개, 최대 5개까지 업로드 가능
50- * - 상품 생성 시 Elasticsearch에도 자동으로 인덱싱됨
51- *
52- * @param request 상품 등록 요청 정보 (JSON)
53- * @param images 상품 이미지 파일 리스트 (최소 1개, 최대 5개)
54- * @param user 현재 로그인한 사용자 정보
55- * @return 생성된 상품의 상세 정보
56- */
5729 @ PostMapping (consumes = MediaType .MULTIPART_FORM_DATA_VALUE )
5830 @ Transactional
5931 public RsData <ProductResponse > createProduct (
32+ @ RequestParam (defaultValue = "STANDARD" ) String productType ,
6033 @ RequestPart ("request" ) @ Valid ProductCreateRequest request ,
6134 @ RequestPart ("images" ) List <MultipartFile > images ,
6235 @ AuthenticationPrincipal User user
6336 ) {
64- Member actor = memberService .findMemberByEmail (user .getUsername ());
65- Product product = productService .createProduct (actor , request , images );
66-
67- ProductResponse response = productMapper .toResponse (product );
37+ ProductResponse response = productFacade .createProduct (productType , request , images , user );
6838 return RsData .created ("상품이 등록되었습니다" , response );
6939 }
7040
71- /**
72- * 상품 목록 조회 (RDB 기반)
73- * - 다양한 필터 조건으로 상품 검색
74- * - QueryDSL을 사용한 동적 쿼리 생성
75- *
76- * @param page 페이지 번호 (1부터 시작, 기본값: 1)
77- * @param size 페이지 크기 (기본값: 20, 최대: 100)
78- * @param keyword 상품명 검색 키워드
79- * @param category 카테고리 ID 배열 (복수 선택 가능)
80- * @param location 거래 지역 배열 (복수 선택 가능)
81- * @param isDelivery 택배 가능 여부 필터
82- * @param status 경매 상태 (BIDDING, BEFORE_START 등)
83- * @param sort 정렬 기준 (LATEST, PRICE_HIGH, PRICE_LOW, ENDING_SOON, POPULAR)
84- * @return 페이징된 상품 목록
85- */
8641 @ GetMapping
8742 @ Transactional (readOnly = true )
8843 public RsData <PageDto <ProductListItemDto >> getProducts (
@@ -96,18 +51,10 @@ public RsData<PageDto<ProductListItemDto>> getProducts(
9651 @ RequestParam (defaultValue = "LATEST" ) ProductSearchSortType sort
9752 ) {
9853 ProductSearchDto search = new ProductSearchDto (keyword , category , location , isDelivery , status );
99- Page <Product > products = productService .findBySearchPaged (page , size , sort , search );
100-
101- PageDto <ProductListItemDto > response = productMapper .toListResponse (products );
54+ PageDto <ProductListItemDto > response = productFacade .getProducts (page , size , sort , search );
10255 return RsData .ok ("상품 목록이 조회되었습니다" , response );
10356 }
10457
105- /**
106- * 상품 목록 조회 (Elasticsearch 기반)
107- * - Elasticsearch의 전문 검색 기능 활용
108- * - 한글 형태소 분석(nori analyzer) 지원
109- * - RDB보다 빠른 검색 성능 제공
110- */
11158 @ GetMapping ("/es" )
11259 @ Transactional (readOnly = true )
11360 public RsData <PageDto <ProductListItemDto >> getProductsByElasticsearch (
@@ -121,42 +68,17 @@ public RsData<PageDto<ProductListItemDto>> getProductsByElasticsearch(
12168 @ RequestParam (required = false ) ProductSearchSortType sort
12269 ) {
12370 ProductSearchDto search = new ProductSearchDto (keyword , category , location , isDelivery , status );
124- Page <ProductDocument > products = productSearchService .searchProducts (page , size , sort , search );
125-
126- PageDto <ProductListItemDto > response = productMapper .toListResponseFromDocument (products );
71+ PageDto <ProductListItemDto > response = productFacade .getProductsByElasticsearch (page , size , sort , search );
12772 return RsData .ok ("상품 목록이 조회되었습니다" , response );
12873 }
12974
130- /**
131- * 상품 상세 조회
132- * - 특정 상품의 모든 정보를 조회
133- * - 이미지 목록, 판매자 정보 포함
134- *
135- * @param productId 조회할 상품의 ID
136- * @return 상품 상세 정보
137- */
13875 @ GetMapping ("/{productId}" )
13976 @ Transactional (readOnly = true )
14077 public RsData <ProductResponse > getProduct (@ PathVariable Long productId ) {
141- Product product = productService .getProductById (productId );
142-
143- ProductResponse response = productMapper .toResponse (product );
78+ ProductResponse response = productFacade .getProduct (productId );
14479 return RsData .ok ("상품이 조회되었습니다" , response );
14580 }
14681
147- /**
148- * 상품 수정
149- * - 상품 정보 수정 및 이미지 추가/삭제
150- * - 경매 시작 전에만 수정 가능
151- * - 본인의 상품만 수정 가능
152- *
153- * @param productId 수정할 상품의 ID
154- * @param request 수정할 상품 정보 (변경할 필드만 포함)
155- * @param images 추가할 이미지 파일 (선택)
156- * @param deleteImageIds 삭제할 이미지 ID 리스트 (선택)
157- * @param user 현재 로그인한 사용자
158- * @return 수정된 상품 정보
159- */
16082 @ PutMapping (value = "/{productId}" , consumes = MediaType .MULTIPART_FORM_DATA_VALUE )
16183 @ Transactional
16284 public RsData <ProductResponse > modifyProduct (
@@ -166,50 +88,21 @@ public RsData<ProductResponse> modifyProduct(
16688 @ RequestPart (value = "deleteImageIds" , required = false ) List <Long > deleteImageIds ,
16789 @ AuthenticationPrincipal User user
16890 ) {
169- Member actor = memberService .findMemberByEmail (user .getUsername ());
170- Product product = productService .getProductById (productId );
171-
172- product .checkActorCanModify (actor );
173-
174- productService .modifyProduct (product , request , images , deleteImageIds );
175-
176- ProductResponse response = productMapper .toResponse (product );
91+ ProductResponse response = productFacade .modifyProduct (productId , request , images , deleteImageIds , user );
17792 return RsData .ok ("상품이 수정되었습니다" , response );
17893 }
17994
180- /**
181- * 상품 삭제
182- * - 경매 시작 전에만 삭제 가능
183- * - 본인의 상품만 삭제 가능
184- * - 관련된 모든 이미지 파일도 함께 삭제됨
185- *
186- * @param productId 삭제할 상품의 ID
187- * @param user 현재 로그인한 사용자
188- */
18995 @ DeleteMapping ("/{productId}" )
19096 @ Transactional
19197 public RsData <Void > deleteProduct (
19298 @ PathVariable Long productId ,
19399 @ AuthenticationPrincipal User user
194100 ) {
195- Member actor = memberService .findMemberByEmail (user .getUsername ());
196- Product product = productService .getProductById (productId );
197-
198- product .checkActorCanDelete (actor );
199-
200- productService .deleteProduct (product );
101+ productFacade .deleteProduct (productId , user );
201102
202103 return RsData .ok ("상품이 삭제되었습니다" );
203104 }
204105
205- /**
206- * 내 상품 목록 조회 (RDB 기반)
207- * - 로그인한 사용자가 등록한 상품 목록 조회
208- * - 판매 상태별 필터링 가능
209- * - 낙찰자 및 리뷰 정보 포함
210- *
211- * @param status 판매 상태 (SELLING, SOLD, FAILED)
212- */
213106 @ GetMapping ("/me" )
214107 @ Transactional (readOnly = true )
215108 public RsData <PageDto <MyProductListItemDto >> getMyProducts (
@@ -219,22 +112,10 @@ public RsData<PageDto<MyProductListItemDto>> getMyProducts(
219112 @ RequestParam (defaultValue = "LATEST" ) ProductSearchSortType sort ,
220113 @ AuthenticationPrincipal User user
221114 ) {
222- Member actor = memberService .findMemberByEmail (user .getUsername ());
223- Page <Product > products = productService .findByMemberPaged (page , size , sort , actor , status );
224-
225- PageDto <MyProductListItemDto > response = productMapper .toMyListResponse (products );
115+ PageDto <MyProductListItemDto > response = productFacade .getMyProducts (page , size , sort , status , user );
226116 return RsData .ok ("내 상품 목록이 조회되었습니다" , response );
227117 }
228118
229- /**
230- * 특정 회원의 상품 목록 조회 (RDB 기반)
231- * - 다른 회원이 등록한 상품 목록 조회
232- * - 판매 상태별 필터링 가능
233- * - 리뷰 정보 포함
234- * - 회원 프로필 페이지 등에서 사용
235- *
236- * @param memberId 조회할 회원의 ID
237- */
238119 @ GetMapping ("/members/{memberId}" )
239120 @ Transactional (readOnly = true )
240121 public RsData <PageDto <ProductListByMemberItemDto >> getProductsByMember (
@@ -244,22 +125,16 @@ public RsData<PageDto<ProductListByMemberItemDto>> getProductsByMember(
244125 @ RequestParam (defaultValue = "SELLING" ) SaleStatus status ,
245126 @ RequestParam (defaultValue = "LATEST" ) ProductSearchSortType sort
246127 ) {
247- Member actor = memberService .findById (memberId ).orElseThrow (ProductException ::memberNotFound );
248-
249- Page <Product > products = productService .findByMemberPaged (page , size , sort , actor , status );
250-
251- PageDto <ProductListByMemberItemDto > response = productMapper .toListByMemberResponse (products );
128+ PageDto <ProductListByMemberItemDto > response = productFacade .getProductsByMember (memberId , page , size , sort , status );
252129 return RsData .ok ("%d번 회원 상품 목록이 조회되었습니다" .formatted (memberId ), response );
253130 }
254131
255132 /**
256- * Elasticsearch 검색 분석기 재로드
257- * 사용자 사전, 동의어 사전 변경 후 호출 필요
258133 * TODO: 관리자만 접근 가능하도록 변경 필요
259134 */
260135 @ PostMapping ("/reload-analyzers" )
261136// @PreAuthorize("hasRole('ADMIN')")
262137 public RsData <ReloadAnalyzersResponse > reloadSearchAnalyzers () {
263- return productSearchService .reloadSearchAnalyzers ();
138+ return productFacade .reloadSearchAnalyzers ();
264139 }
265140}
0 commit comments