Skip to content

Commit 172bd2a

Browse files
authored
Merge pull request #14 from Decodeat/feat/13-product-my-regist
[Feat] 나의 분석 요청 기록 api
2 parents 3446abc + 36efbca commit 172bd2a

File tree

6 files changed

+77
-26
lines changed

6 files changed

+77
-26
lines changed

src/main/java/com/DecodEat/domain/products/controller/ProductController.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package com.DecodEat.domain.products.controller;
22

3-
import com.DecodEat.domain.products.dto.response.ProductDetailDto;
3+
import com.DecodEat.domain.products.dto.response.*;
44
import com.DecodEat.domain.products.dto.request.ProductRegisterRequestDto;
5-
import com.DecodEat.domain.products.dto.response.ProductRegisterResponseDto;
6-
import com.DecodEat.domain.products.dto.response.ProductResponseDTO;
7-
import com.DecodEat.domain.products.dto.response.ProductSearchResponseDto;
85
import com.DecodEat.domain.products.entity.RawMaterial.RawMaterialCategory;
96
import com.DecodEat.domain.products.service.ProductService;
107
import com.DecodEat.domain.users.entity.User;
@@ -44,7 +41,8 @@ public ApiResponse<ProductDetailDto> getProduct(@PathVariable Long id) {
4441
@Operation(
4542
summary = "제품 등록",
4643
description = "상품 이미지, 제품명, 회사명으로 상품을 등록합니다")
47-
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE) //이 엔드포인트가 multipart/form-data 타입의 요청 본문을 소비(consume)한다는 것을 명확하게 선언
44+
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
45+
//이 엔드포인트가 multipart/form-data 타입의 요청 본문을 소비(consume)한다는 것을 명확하게 선언
4846
public ApiResponse<ProductRegisterResponseDto> registerProduct(
4947
@CurrentUser User user,
5048
@RequestParam("name") String name,
@@ -90,8 +88,20 @@ public ApiResponse<PageResponseDto<ProductSearchResponseDto.ProductPrevDto>> sea
9088
@RequestParam(defaultValue = "1") int page,
9189
@RequestParam(defaultValue = "20") int size) {
9290

93-
Pageable pageable = PageRequest.of(page-1, size, Sort.by("productName").ascending()); // 0-based
91+
Pageable pageable = PageRequest.of(page - 1, size, Sort.by("productName").ascending()); // 0-based
9492
return ApiResponse.onSuccess(productService.searchProducts(productName, categories, pageable));
9593
}
9694

95+
@GetMapping("/register-history")
96+
@Operation(summary = "나의 분석 요청 기록", description = "내가 등록한 상품의 분석 결과 목록입니다.")
97+
public ApiResponse<PageResponseDto<ProductRegisterHistoryDto>> getRegisterHistory(@CurrentUser User user,
98+
@RequestParam(defaultValue = "1") int page,
99+
@RequestParam(defaultValue = "20") int size) {
100+
101+
Pageable pageable = PageRequest.of(page - 1, size, Sort.by("createdAt").descending()); // 0-based
102+
103+
return ApiResponse.onSuccess(productService.getRegisterHistory(user, pageable));
104+
}
105+
106+
97107
}

src/main/java/com/DecodEat/domain/products/converter/ProductConverter.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package com.DecodEat.domain.products.converter;
22

3-
import com.DecodEat.domain.products.dto.response.ProductDetailDto;
4-
import com.DecodEat.domain.products.dto.response.ProductRegisterResponseDto;
5-
import com.DecodEat.domain.products.dto.response.ProductResponseDTO;
6-
import com.DecodEat.domain.products.dto.response.ProductSearchResponseDto;
3+
import com.DecodEat.domain.products.dto.request.ProductRegisterRequestDto;
4+
import com.DecodEat.domain.products.dto.response.*;
75
import com.DecodEat.domain.products.entity.Product;
86
import com.DecodEat.domain.products.entity.ProductNutrition;
97
import com.DecodEat.domain.products.entity.RawMaterial.RawMaterialCategory;
@@ -94,6 +92,16 @@ public static ProductSearchResponseDto.ProductPrevDto toProductPrevDto(Product p
9492
.build();
9593
}
9694

95+
public static ProductRegisterHistoryDto toProductRegisterHistoryDto(Product product){
96+
return ProductRegisterHistoryDto.builder()
97+
.productId(product.getProductId())
98+
.registerDate(product.getCreatedAt())
99+
.productImage(product.getProductImage())
100+
.decodeStatus(product.getDecodeStatus())
101+
.build();
102+
}
103+
104+
97105
// Slice<Product> → ProductListResultDTO 변환
98106
public static ProductResponseDTO.ProductListResultDTO toProductListResultDTO(Slice<Product> slice) {
99107
List<ProductResponseDTO.ProductListItemDTO> productList = slice.getContent().stream()
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.DecodEat.domain.products.dto.response;
2+
3+
import com.DecodEat.domain.products.entity.DecodeStatus;
4+
import com.fasterxml.jackson.annotation.JsonFormat;
5+
import io.swagger.v3.oas.annotations.media.Schema;
6+
import lombok.Builder;
7+
import lombok.Getter;
8+
9+
import java.time.LocalDateTime;
10+
11+
@Getter
12+
@Builder
13+
public class ProductRegisterHistoryDto {
14+
15+
@Schema(description = "상품 ID", example = "1")
16+
private Long productId;
17+
18+
@Schema(description = "상품 등록일", example = "2025-09-05")
19+
@JsonFormat(pattern = "yyyy-MM-dd")
20+
private LocalDateTime registerDate;
21+
22+
@Schema(description = "상품 이미지", example = "https://example.com/image.jpg")
23+
private String productImage;
24+
25+
@Schema(description = "분석 상태", example = "COMPLETED")
26+
private DecodeStatus decodeStatus;
27+
}

src/main/java/com/DecodEat/domain/products/repository/ProductRepository.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.DecodEat.domain.products.entity.DecodeStatus;
44
import com.DecodEat.domain.products.entity.Product;
5+
import com.DecodEat.domain.users.entity.User;
6+
import org.springframework.data.domain.Page;
57
import org.springframework.data.domain.Pageable;
68
import org.springframework.data.domain.Slice;
79
import org.springframework.data.jpa.repository.JpaRepository;
@@ -22,4 +24,6 @@ Slice<Product> findCompletedProductsByCursor(@Param("cursorId") Long cursorId,
2224
Pageable pageable);
2325

2426
void deleteByDecodeStatusIn(List<DecodeStatus> statuses);
27+
28+
Page<Product> findByUserId(Long userId, Pageable pageable);
2529
}

src/main/java/com/DecodEat/domain/products/service/ProductService.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22

33
import com.DecodEat.domain.products.converter.ProductConverter;
44
import com.DecodEat.domain.products.dto.request.ProductRegisterRequestDto;
5-
import com.DecodEat.domain.products.dto.response.ProductDetailDto;
6-
import com.DecodEat.domain.products.dto.response.ProductRegisterResponseDto;
7-
import com.DecodEat.domain.products.dto.response.ProductResponseDTO;
8-
import com.DecodEat.domain.products.dto.response.ProductSearchResponseDto;
5+
import com.DecodEat.domain.products.dto.response.*;
96
import com.DecodEat.domain.products.entity.DecodeStatus;
107
import com.DecodEat.domain.products.entity.Product;
118
import com.DecodEat.domain.products.entity.ProductInfoImage;
@@ -145,4 +142,14 @@ public PageResponseDto<ProductSearchResponseDto.ProductPrevDto> searchProducts(S
145142

146143
return new PageResponseDto<>(result);
147144
}
145+
146+
public PageResponseDto<ProductRegisterHistoryDto> getRegisterHistory(User user, Pageable pageable){
147+
148+
Long userId = user.getId();
149+
150+
Page<Product> pagedProducts = productRepository.findByUserId(userId, pageable);
151+
Page<ProductRegisterHistoryDto> result = pagedProducts.map(ProductConverter::toProductRegisterHistoryDto);
152+
153+
return new PageResponseDto<>(result);
154+
}
148155
}

src/main/java/com/DecodEat/global/config/CurrentUserArgumentResolver.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,19 @@ public class CurrentUserArgumentResolver implements HandlerMethodArgumentResolve
2121
@Override
2222
public boolean supportsParameter(org.springframework.core.MethodParameter parameter) {
2323
return parameter.getParameterAnnotation(CurrentUser.class) != null
24-
&& parameter.getParameterType().equals(com.DecodEat.domain.users.entity.User.class);
24+
&& parameter.getParameterType().equals(com.DecodEat.domain.users.entity.User.class);
2525
}
2626

2727
@Override
2828
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
29-
try {
30-
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
3129

32-
if (principal instanceof org.springframework.security.core.userdetails.User) {
33-
org.springframework.security.core.userdetails.User springUser = (org.springframework.security.core.userdetails.User) principal;
34-
Long userId = Long.valueOf(springUser.getUsername());
35-
return userService.findById(userId); // userId로 User 엔티티를 찾아 반환
36-
}
37-
} catch (Exception e) {
38-
// 예외 처리, 인증되지 않은 사용자의 경우 null 또는 예외를 던질 수 있습니다.
39-
throw new GeneralException(ErrorStatus._UNAUTHORIZED);
30+
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
31+
32+
if (principal instanceof org.springframework.security.core.userdetails.User springUser) {
33+
Long userId = Long.valueOf(springUser.getUsername());
34+
return userService.findById(userId); // userId로 User 엔티티를 찾아 반환
4035
}
4136

42-
return null;
37+
throw new GeneralException(ErrorStatus._UNAUTHORIZED);
4338
}
4439
}

0 commit comments

Comments
 (0)