Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 1.0.8 #94

Merged
merged 28 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
00bab51
rename: dto 패키지 분리
koo995 Oct 11, 2024
eaf8193
feat: 식품명과 제조사명으로 식품을 검색한다.
koo995 Oct 11, 2024
b8db9cc
fix: @Transactional 추가
koo995 Oct 20, 2024
613ce60
refactor: JdbcAuditing 으로 생성일, 수정일 적용
koo995 Oct 20, 2024
4a598c9
chore: 불필요한 import 제거
koo995 Oct 20, 2024
3af6960
chore: 더미데이터 추가 로직 작성
koo995 Oct 20, 2024
5ba467d
refactor: 리뷰 갯수와 함께 식품 검색
koo995 Oct 21, 2024
9f7055f
chore: 더미데이터 삽입 코드 주석처리
koo995 Oct 21, 2024
993b3e4
refactor: 식품 검색 쿼리 수정
koo995 Oct 22, 2024
8014928
refactor: 외래키를 제거한 부분에 인덱스 추가
koo995 Oct 22, 2024
215c04f
refactor: 식품 조회시 top3 diet tag 추가
koo995 Oct 22, 2024
e04f4e9
rename: file 저장 로직 패키지변경
koo995 Oct 22, 2024
d47292b
refactor: 검색 프로세스 변경.
koo995 Nov 14, 2024
f796de4
Merge pull request #85 from f-lab-edu/feature/#76
koo995 Nov 14, 2024
22571d6
feat: 도커 컨테이너 설정
koo995 Dec 1, 2024
bb7f548
Merge pull request #89 from f-lab-edu/feature/#80
koo995 Dec 1, 2024
05debe2
refactor: jacoco을 활용하여 테스트 코드 커버리지를 측정
koo995 Dec 1, 2024
7fce4e5
Merge pull request #90 from f-lab-edu/feature/#88
koo995 Dec 1, 2024
78d8ff6
chore: jacoco 폴더 gitignore 추가
koo995 Dec 1, 2024
890355d
chore: Jdk 17로 변경
koo995 Dec 5, 2024
7d49deb
fix: Jdk 17로 변경
koo995 Dec 5, 2024
a1b0d63
feat: 모든 Store을 조회한다.
koo995 Dec 12, 2024
182e9de
fix: 클래스 패키지 변경
koo995 Dec 12, 2024
b0a0749
feat: productIds로 조회하는 메서드 추가
koo995 Dec 12, 2024
41fcbb2
rename: 레포지토리 인터페이스명 변경
koo995 Dec 12, 2024
fe9eb42
rename: ProductStore에서 StoreProduct로 스키마 변경
koo995 Dec 12, 2024
92184d8
feat: store에 해당하는 식품들을 조회한다.
koo995 Dec 13, 2024
9e63d89
Merge pull request #93 from f-lab-edu/feature/#92
koo995 Dec 13, 2024
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,6 @@ out/

### VS Code ###
.vscode/

### jacoco ###
jacoco/
50 changes: 49 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ plugins {
id 'java'
id 'org.springframework.boot' version '3.3.2'
id 'io.spring.dependency-management' version '1.1.6'
id 'jacoco'
}

group = 'flab'
version = '0.0.1-SNAPSHOT'

java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
languageVersion = JavaLanguageVersion.of(17)
}
}

Expand Down Expand Up @@ -47,4 +48,51 @@ dependencies {

tasks.named('test') {
useJUnitPlatform()
finalizedBy jacocoTestReport
}

jacocoTestReport {
dependsOn test
reports {
html.required = true
html.destination file("jacoco/report.html")
}
// finalizedBy 'jacocoTestCoverageVerification'
}

// jacoco 커버리지 검증 설정
//jacocoTestCoverageVerification {
// violationRules {
// rule {
// enabled = true // 커버리지 적용 여부
// element = 'CLASS' // 커버리지 적용 단위
//
// // 라인 커버리지 설정
// // 적용 대상 전체 소스 코드들을 한줄 한줄 따졌을 때 테스트 코드가 작성되어 있는 줄의 빈도
// // 테스트 코드가 작성되어 있는 비율이 90% 이상이어야 함
// limit {
// counter = 'LINE'
// value = 'COVEREDRATIO'
// minimum = 0.80
// }
//
// // 브랜치 커버리지 설정
// // if-else 등을 활용하여 발생되는 분기들 중 테스트 코드가 작성되어 있는 빈도
// // 테스트 코드가 작성되어 있는 비율이 90% 이상이어야 함
// limit {
// counter = 'BRANCH'
// value = 'COVEREDRATIO'
// minimum = 0.80
// }
//
// // 라인 최대 갯수 설정
// // 빈 줄을 제외하고 하나의 자바 파일에서 작성될 수 있는 최대 라인 갯수
// // 한 파일에 최대 500줄까지 작성되어야 함
// limit {
// counter = 'LINE'
// value = 'TOTALCOUNT'
// maximum = 500
// }
// }
// }
//}
2 changes: 1 addition & 1 deletion src/main/java/flab/nutridiary/commom/config/S3Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import flab.nutridiary.commom.file.S3FileStore;
import flab.nutridiary.file.S3FileStore;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ public enum StatusConst {
DUPLICATED_DIARY(4005, "이미 등록된 다이어리입니다."),
VALIDATION_CHECK_FAIL(6001, "유효성 검사에 실패했습니다."),
NOT_ALLOWED_SERVING_UNIT(6002, "허용되지 않은 서빙 단위입니다."),
DUPLICATED_PRODUCT_REVIEW(4006, "이미 등록된 리뷰입니다.");
DUPLICATED_PRODUCT_REVIEW(4006, "이미 등록된 리뷰입니다."),
STORE_PRODUCT_NOT_FOUND(4007, "해당 매장에 등록된 상품이 없습니다."),;

private final int statusCode;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
import flab.nutridiary.diary.domain.Diary;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.Optional;

@Repository
@RequiredArgsConstructor
@Transactional
@Repository
public class DiaryRepositoryImpl implements DiaryRepository{
private final DiaryCrudRepository diaryCrudRepository;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package flab.nutridiary.commom.file;
package flab.nutridiary.file;

import org.springframework.web.multipart.MultipartFile;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package flab.nutridiary.commom.file;
package flab.nutridiary.file;


import com.amazonaws.services.s3.AmazonS3;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,31 @@
package flab.nutridiary.product.controller;

import flab.nutridiary.commom.dto.ApiResponse;
import flab.nutridiary.product.dto.NewProductRequest;
import flab.nutridiary.product.dto.NewProductResponse;
import flab.nutridiary.product.dto.request.NewProductRequest;
import flab.nutridiary.product.dto.response.NewProductResponse;
import flab.nutridiary.product.dto.response.ProductSearchResponse;
import flab.nutridiary.product.service.ProductRegisterService;
import flab.nutridiary.product.service.ProductSearchService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
public class ProductController {

private final ProductRegisterService productRegisterService;
private final ProductSearchService productSearchService;

@PostMapping("/product/new")
public ApiResponse<NewProductResponse> addProduct(@RequestBody @Valid NewProductRequest productRequest) {
return ApiResponse.success(productRegisterService.process(productRequest));
}

@GetMapping("/product")
public ApiResponse<Page<ProductSearchResponse>> searchProduct(@RequestParam(name = "search") String condition, Pageable pageable) {
return ApiResponse.success(productSearchService.search(condition, pageable));
}
}
7 changes: 4 additions & 3 deletions src/main/java/flab/nutridiary/product/domain/Product.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.relational.core.mapping.Column;

import java.time.LocalDateTime;
Expand All @@ -29,10 +30,10 @@ public class Product {

private Long memberId = 1L;

@Setter
@CreatedDate
private LocalDateTime createdAt;

@Setter
@LastModifiedDate
private LocalDateTime updatedAt;

@Builder
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package flab.nutridiary.product.domain;

import flab.nutridiary.product.dto.NewProductRequest;
import flab.nutridiary.product.dto.request.NewProductRequest;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package flab.nutridiary.product.dto;
package flab.nutridiary.product.dto.request;

import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package flab.nutridiary.product.dto;
package flab.nutridiary.product.dto.response;

import lombok.Getter;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package flab.nutridiary.product.dto.response;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;

import java.math.BigDecimal;
import java.math.RoundingMode;

@Getter
@EqualsAndHashCode
@ToString
public class ProductSearchResponse {
private Long productId;
private String productName;
private String productCorp;
private Integer reviewCount;
private BigDecimal reviewAvgRating;
private String top3_diet_tag_names;

public ProductSearchResponse(Long productId, String productName, String productCorp, Integer reviewCount, BigDecimal reviewAvgRating, String top3_diet_tag_names) {
this.productId = productId;
this.productName = productName;
this.productCorp = productCorp;
this.reviewCount = reviewCount;
this.reviewAvgRating = reviewAvgRating == null ? BigDecimal.ZERO : reviewAvgRating.setScale(1, RoundingMode.HALF_UP);
this.top3_diet_tag_names = top3_diet_tag_names;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package flab.nutridiary.product.repository;

import flab.nutridiary.product.domain.Product;
import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface ProductCrudRepository extends CrudRepository<Product, Long> {
int countByProductNormalizedName(String normalizedName);

@Query("SELECT * FROM product WHERE product_id IN (:productIds)")
List<Product> findByIds(List<Long> productIds);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import flab.nutridiary.product.domain.Product;

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

public interface ProductRepository {
Product save(Product product);
Optional<Product> findById(Long id);
List<Product> findByIds(List<Long> ids);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
import flab.nutridiary.product.service.ProductValidatorRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

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

@Repository
@RequiredArgsConstructor
@Transactional
@Repository
public class ProductRepositoryImpl implements ProductRepository, ProductValidatorRepository {

private final ProductCrudRepository productCrudRepository;
Expand All @@ -23,6 +26,11 @@ public Optional<Product> findById(Long id) {
return productCrudRepository.findById(id);
}

@Override
public List<Product> findByIds(List<Long> ids) {
return productCrudRepository.findByIds(ids);
}

@Override
public Boolean isExistDuplicatedProductByNormalizedName(String normalizedName) {
return productCrudRepository.countByProductNormalizedName(normalizedName) > 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package flab.nutridiary.product.repository;

import flab.nutridiary.product.dto.response.ProductSearchResponse;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface ProductSearchRepository {
Page<ProductSearchResponse> findFullTextSearch(String keyword, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package flab.nutridiary.product.repository.query;

import flab.nutridiary.product.dto.response.ProductSearchResponse;
import flab.nutridiary.product.repository.ProductSearchRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.DataClassRowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Repository
@RequiredArgsConstructor
@Transactional
public class JdbcTemplateProductSearchRepository implements ProductSearchRepository {
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
DataClassRowMapper<ProductSearchResponse> beanPropertyRowMapper = new DataClassRowMapper<>(ProductSearchResponse.class);


@Override
public Page<ProductSearchResponse> findFullTextSearch(String keyword, Pageable pageable) {
Integer total = getTotalCount(keyword);

String sql = "SELECT " +
"p.product_id, p.product_name, p.product_corp, " +
"(SELECT COUNT(*) FROM review r WHERE r.product_id = p.product_id) AS review_count, " +
"(SELECT AVG(r.rating) FROM review r WHERE r.product_id = p.product_id) AS review_avg_rating, " +
"(SELECT GROUP_CONCAT(diet_plan) FROM (SELECT dt.diet_plan FROM product_diet_tag pdt JOIN diet_tag dt ON pdt.diet_tag_id = dt.diet_tag_id where pdt.product_id = p.product_id ORDER BY pdt.tag_count DESC LIMIT 3) AS top3_diet_tag) AS top3_diet_tag_names " +
"FROM product p " +
"WHERE MATCH (p.product_name, p.product_corp) AGAINST (:keyword)" +
"LIMIT :offset, :limit";
MapSqlParameterSource parameters = new MapSqlParameterSource()
.addValue("keyword", keyword)
.addValue("offset", pageable.getOffset())
.addValue("limit", pageable.getPageSize());
List<ProductSearchResponse> queried = namedParameterJdbcTemplate.query(sql, parameters, beanPropertyRowMapper);
return new PageImpl<>(queried, pageable, total);
}

private Integer getTotalCount(String keyword) {
String sql = "SELECT COUNT(*) " +
"FROM product p " +
"WHERE MATCH (p.product_name, p.product_corp) AGAINST (:keyword)";
MapSqlParameterSource parameters = new MapSqlParameterSource()
.addValue("keyword", keyword);
return namedParameterJdbcTemplate.queryForObject(sql, parameters, Integer.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import flab.nutridiary.product.domain.Product;
import flab.nutridiary.product.domain.ProductMapper;
import flab.nutridiary.product.dto.NewProductRequest;
import flab.nutridiary.product.dto.NewProductResponse;
import flab.nutridiary.product.dto.request.NewProductRequest;
import flab.nutridiary.product.dto.response.NewProductResponse;
import flab.nutridiary.product.repository.ProductRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down
Loading
Loading