Skip to content

Commit

Permalink
Merge branch 'develop' into feat/issue-669
Browse files Browse the repository at this point in the history
  • Loading branch information
hanueleee authored Oct 16, 2023
2 parents 25e449c + 62124a6 commit 8c186e9
Show file tree
Hide file tree
Showing 177 changed files with 4,598 additions and 2,051 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test-fe.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
continue-on-error: true

- name: 테스트 결과 PR에 코멘트 등록
uses: EnricoMi/publish-unit-test-result-action@v1
uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
files: '**/frontend/test-results/results.xml'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
run: ./gradlew --info test

- name: 테스트 결과 PR에 코멘트 등록
uses: EnricoMi/publish-unit-test-result-action@v1
uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
files: '**/backend/build/test-results/test/TEST-*.xml'
Expand Down
2 changes: 2 additions & 0 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ dependencies {
runtimeOnly 'io.micrometer:micrometer-registry-prometheus'

implementation 'com.amazonaws:aws-java-sdk-s3:1.12.547'

implementation 'org.springframework.session:spring-session-jdbc'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.funeat.admin.application;

import com.funeat.admin.domain.AdminAuthInfo;
import com.funeat.auth.exception.AuthErrorCode;
import com.funeat.auth.exception.AuthException.NotLoggedInException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class AdminChecker {

@Value("${back-office.id}")
private String id;

@Value("${back-office.key}")
private String key;

public boolean check(final AdminAuthInfo adminAuthInfo) {
if (!id.equals(adminAuthInfo.getId())) {
throw new NotLoggedInException(AuthErrorCode.LOGIN_ADMIN_NOT_FOUND);
}

if (!key.equals(adminAuthInfo.getKey())) {
throw new NotLoggedInException(AuthErrorCode.LOGIN_ADMIN_NOT_FOUND);
}

return true;
}
}
117 changes: 117 additions & 0 deletions backend/src/main/java/com/funeat/admin/application/AdminService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package com.funeat.admin.application;

import static com.funeat.product.exception.CategoryErrorCode.CATEGORY_NOT_FOUND;
import static com.funeat.product.exception.ProductErrorCode.PRODUCT_NOT_FOUND;

import com.funeat.admin.dto.AdminProductResponse;
import com.funeat.admin.dto.AdminProductSearchResponse;
import com.funeat.admin.dto.AdminReviewResponse;
import com.funeat.admin.dto.AdminReviewSearchResponse;
import com.funeat.admin.dto.ProductCreateRequest;
import com.funeat.admin.dto.ProductSearchCondition;
import com.funeat.admin.dto.ProductUpdateRequest;
import com.funeat.admin.dto.ReviewSearchCondition;
import com.funeat.admin.repository.AdminProductRepository;
import com.funeat.admin.repository.AdminReviewRepository;
import com.funeat.admin.specification.AdminProductSpecification;
import com.funeat.admin.specification.AdminReviewSpecification;
import com.funeat.product.domain.Category;
import com.funeat.product.domain.Product;
import com.funeat.product.dto.CategoryResponse;
import com.funeat.product.exception.CategoryException.CategoryNotFoundException;
import com.funeat.product.exception.ProductException.ProductNotFoundException;
import com.funeat.product.persistence.CategoryRepository;
import com.funeat.product.persistence.ProductRepository;
import com.funeat.review.domain.Review;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
public class AdminService {

private static final int DEFAULT_PAGE_SIZE = 10;

private final ProductRepository productRepository;
private final AdminProductRepository adminProductRepository;
private final CategoryRepository categoryRepository;
private final AdminReviewRepository adminReviewRepository;

public AdminService(final ProductRepository productRepository, final AdminProductRepository adminProductRepository,
final CategoryRepository categoryRepository, final AdminReviewRepository adminReviewRepository) {
this.productRepository = productRepository;
this.adminProductRepository = adminProductRepository;
this.categoryRepository = categoryRepository;
this.adminReviewRepository = adminReviewRepository;
}

@Transactional
public Long addProduct(final ProductCreateRequest request) {
final Category findCategory = categoryRepository.findById(request.getCategoryId())
.orElseThrow(() -> new CategoryNotFoundException(CATEGORY_NOT_FOUND, request.getCategoryId()));

final Product product = Product.create(request.getName(), request.getPrice(), request.getContent(),
findCategory);

return productRepository.save(product).getId();
}

public List<CategoryResponse> getAllCategories() {
final List<Category> findCategories = categoryRepository.findAll();

return findCategories.stream()
.map(CategoryResponse::toResponse)
.collect(Collectors.toList());
}

public AdminProductSearchResponse getSearchProducts(final ProductSearchCondition condition,
final Pageable pageable) {
final Specification<Product> specification = AdminProductSpecification.searchBy(condition);

final Page<Product> findProducts = adminProductRepository.findAllForPagination(specification, pageable,
condition.getTotalElements());

final List<AdminProductResponse> productResponses = findProducts.stream()
.map(AdminProductResponse::toResponse)
.collect(Collectors.toList());

final Boolean isLastPage = isLastPage(findProducts, condition.getPrePage());

return new AdminProductSearchResponse(productResponses, findProducts.getTotalElements(), isLastPage);
}

private <T> boolean isLastPage(final Page<T> findProducts, Long prePage) {
return prePage * DEFAULT_PAGE_SIZE + findProducts.getContent().size() == findProducts.getTotalElements();
}

@Transactional
public void updateProduct(final Long productId, final ProductUpdateRequest request) {
final Product findProduct = productRepository.findById(productId)
.orElseThrow(() -> new ProductNotFoundException(PRODUCT_NOT_FOUND, productId));

final Category findCategory = categoryRepository.findById(request.getCategoryId())
.orElseThrow(() -> new CategoryNotFoundException(CATEGORY_NOT_FOUND, request.getCategoryId()));

findProduct.update(request.getName(), request.getContent(), request.getPrice(), findCategory);
}

public AdminReviewSearchResponse getSearchReviews(final ReviewSearchCondition condition, final Pageable pageable) {
final Specification<Review> specification = AdminReviewSpecification.searchBy(condition);

final Page<Review> findReviews = adminReviewRepository.findAllForPagination(specification, pageable,
condition.getTotalElements());

final List<AdminReviewResponse> reviewResponses = findReviews.stream()
.map(AdminReviewResponse::toResponse)
.collect(Collectors.toList());

final Boolean isLastPage = isLastPage(findReviews, condition.getPrePage());

return new AdminReviewSearchResponse(reviewResponses, findReviews.getTotalElements(), isLastPage);
}
}
20 changes: 20 additions & 0 deletions backend/src/main/java/com/funeat/admin/domain/AdminAuthInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.funeat.admin.domain;

public class AdminAuthInfo {

private final String id;
private final String key;

public AdminAuthInfo(final String id, final String key) {
this.id = id;
this.key = key;
}

public String getId() {
return id;
}

public String getKey() {
return key;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.funeat.admin.dto;

import com.funeat.product.domain.Category;

public class AdminCategoryResponse {

private final Long id;
private final String name;
private final String image;

public AdminCategoryResponse(final Long id, final String name, final String image) {
this.id = id;
this.name = name;
this.image = image;
}

public static AdminCategoryResponse toResponse(final Category category) {
return new AdminCategoryResponse(category.getId(), category.getName(), category.getImage());
}

public Long getId() {
return id;
}

public String getName() {
return name;
}

public String getImage() {
return image;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.funeat.admin.dto;

import com.funeat.product.domain.Product;

public class AdminProductResponse {

private final Long id;
private final String name;
private final String content;
private final Long price;
private final AdminCategoryResponse categoryResponse;

private AdminProductResponse(final Long id, final String name, final String content,
final Long price, final AdminCategoryResponse categoryResponse) {
this.id = id;
this.name = name;
this.content = content;
this.price = price;
this.categoryResponse = categoryResponse;
}

public static AdminProductResponse toResponse(final Product product) {
final AdminCategoryResponse categoryResponse = AdminCategoryResponse.toResponse(product.getCategory());

return new AdminProductResponse(product.getId(), product.getName(), product.getContent(), product.getPrice(),
categoryResponse);
}

public Long getId() {
return id;
}

public String getName() {
return name;
}

public String getContent() {
return content;
}

public Long getPrice() {
return price;
}

public AdminCategoryResponse getCategoryResponse() {
return categoryResponse;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.funeat.admin.dto;

import java.util.List;

public class AdminProductSearchResponse {

private final List<AdminProductResponse> productResponses;
private final Long totalElements;
private final Boolean isLastPage;

public AdminProductSearchResponse(final List<AdminProductResponse> productResponses, final Long totalElements,
final Boolean isLastPage) {
this.productResponses = productResponses;
this.totalElements = totalElements;
this.isLastPage = isLastPage;
}

public List<AdminProductResponse> getProductResponses() {
return productResponses;
}

public Long getTotalElements() {
return totalElements;
}

public Boolean isLastPage() {
return isLastPage;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.funeat.admin.dto;

import com.funeat.review.domain.Review;
import java.time.LocalDateTime;

public class AdminReviewResponse {

private final Long id;
private final String userName;
private final String content;
private final String image;
private final String productName;
private final LocalDateTime createdAt;

private AdminReviewResponse(final Long id, final String userName, final String content,
final String image, final String productName,
final LocalDateTime createdAt) {
this.id = id;
this.userName = userName;
this.content = content;
this.image = image;
this.productName = productName;
this.createdAt = createdAt;
}

public static AdminReviewResponse toResponse(final Review review) {
return new AdminReviewResponse(review.getId(), review.getMember().getNickname(), review.getContent(),
review.getImage(), review.getProduct().getName(), review.getCreatedAt());
}

public Long getId() {
return id;
}

public String getUserName() {
return userName;
}

public String getContent() {
return content;
}

public String getImage() {
return image;
}

public String getProductName() {
return productName;
}

public LocalDateTime getCreatedAt() {
return createdAt;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.funeat.admin.dto;

import java.util.List;

public class AdminReviewSearchResponse {

private final List<AdminReviewResponse> reviewResponses;
private final Long totalElements;
private final Boolean isLastPage;

public AdminReviewSearchResponse(final List<AdminReviewResponse> reviewResponses, final Long totalElements,
final Boolean isLastPage) {
this.reviewResponses = reviewResponses;
this.totalElements = totalElements;
this.isLastPage = isLastPage;
}

public List<AdminReviewResponse> getReviewResponses() {
return reviewResponses;
}

public Long getTotalElements() {
return totalElements;
}

public Boolean getLastPage() {
return isLastPage;
}
}
Loading

0 comments on commit 8c186e9

Please sign in to comment.