From 5e3ef144b2806f7c0ab9f10eb2492ffc9a7b11c8 Mon Sep 17 00:00:00 2001 From: hye-0000 Date: Mon, 10 Jul 2023 14:58:50 +0900 Subject: [PATCH 01/26] =?UTF-8?q?refactor:=20service/serviceImpl=EB=A1=9C?= =?UTF-8?q?=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/answer/service/AnswerService.java | 73 +---------- .../answer/service/AnswerServiceImpl.java | 73 +++++++++++ .../category/service/MainCategoryService.java | 55 ++------ .../service/MainCategoryServiceImpl.java | 56 +++++++++ .../category/service/SubCategoryService.java | 55 ++------ .../service/SubCategoryServiceImpl.java | 62 +++++++++ .../recommend/service/RecommendService.java | 61 +-------- .../service/RecommendServiceImpl.java | 62 +++++++++ .../domain/review/service/ReviewService.java | 99 ++------------- .../review/service/ReviewServiceImpl.java | 119 ++++++++++++++++++ .../tosspayment/service/PaymentService.java | 61 +-------- .../service/PaymentServiceImpl.java | 63 ++++++++++ 12 files changed, 472 insertions(+), 367 deletions(-) create mode 100644 src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java create mode 100644 src/main/java/project/trendpick_pro/domain/category/service/MainCategoryServiceImpl.java create mode 100644 src/main/java/project/trendpick_pro/domain/category/service/SubCategoryServiceImpl.java create mode 100644 src/main/java/project/trendpick_pro/domain/recommend/service/RecommendServiceImpl.java create mode 100644 src/main/java/project/trendpick_pro/domain/review/service/ReviewServiceImpl.java create mode 100644 src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentServiceImpl.java diff --git a/src/main/java/project/trendpick_pro/domain/answer/service/AnswerService.java b/src/main/java/project/trendpick_pro/domain/answer/service/AnswerService.java index 8e7dde8b..c66cb502 100644 --- a/src/main/java/project/trendpick_pro/domain/answer/service/AnswerService.java +++ b/src/main/java/project/trendpick_pro/domain/answer/service/AnswerService.java @@ -1,76 +1,15 @@ package project.trendpick_pro.domain.answer.service; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import project.trendpick_pro.domain.answer.entity.Answer; -import project.trendpick_pro.domain.answer.entity.dto.request.AnswerRequest; import project.trendpick_pro.domain.answer.entity.dto.response.AnswerResponse; import project.trendpick_pro.domain.answer.entity.form.AnswerForm; -import project.trendpick_pro.domain.answer.repository.AnswerRepository; -import project.trendpick_pro.domain.ask.entity.Ask; -import project.trendpick_pro.domain.ask.entity.dto.response.AskResponse; -import project.trendpick_pro.domain.ask.repository.AskRepository; -import project.trendpick_pro.domain.ask.service.AskService; import project.trendpick_pro.domain.member.entity.Member; -import project.trendpick_pro.domain.member.entity.RoleType; import project.trendpick_pro.global.rsData.RsData; import java.util.List; -import java.util.Objects; -@Service -@Transactional(readOnly = true) -@RequiredArgsConstructor -public class AnswerService { - private final AnswerRepository answerRepository; - private final AskRepository askRepository; - - @Transactional - public RsData register(Member member, Long askId, AnswerForm answerForm) { - Ask ask = askRepository.findById(askId).orElseThrow( - () -> new IllegalArgumentException("해당 문의는 없는 문의입니다.") - ); - if (!member.getBrand().equals(ask.getProduct().getBrand().getName())) - return RsData.of("F-1", "타 브랜드 상품에 대한 문의글에는 답변 권한이 없습니다."); - - Answer answer = Answer.write(answerForm); - answer.connectAsk(ask); - answerRepository.save(answer); - return RsData.of("S-1", "답변이 성공적으로 등록되었습니다.", ask.getId()); - } - - @Transactional - public RsData delete(Member member, Long answerId) { - Answer answer = answerRepository.findById(answerId).orElseThrow( - () -> new IllegalArgumentException("해당 답변은 없는 답변입니다.") - ); - - if(!answer.getAsk().getProduct().getBrand().equals(member.getBrand())) - return RsData.of("F-1", "접근 권한이 없습니다."); - - Ask ask = answer.getAsk(); - ask.getAnswerList().remove(answer); - if(ask.getAnswerList().size() == 0) - ask.changeStatusYet(); - - return RsData.of("S-1", "답변이 삭제되었습니다.", answer.getAsk().getId()); - } - - public RsData modify(Member member, Long answerId, AnswerForm answerForm) { - Answer answer = answerRepository.findById(answerId).orElseThrow( - () -> new IllegalArgumentException("해당 답변은 없는 답변입니다.") - ); - - if(!Objects.equals(answer.getAsk().getAuthor().getBrand(), member.getBrand())) - return RsData.of("F-1", "접근 권한이 없습니다."); - answer.update(answerForm); - - return RsData.of("S-1", "답변이 수정되었습니다.", answer.getAsk().getId()); - } - - public List showAll(Long askId) { - List answers = answerRepository.findAllByAskId(askRepository.findById(askId).get()); - return AnswerResponse.of(answers); - } -} \ No newline at end of file +public interface AnswerService { + RsData register(Member member, Long askId, AnswerForm answerForm); + RsData delete(Member member, Long answerId); + RsData modify(Member member, Long answerId, AnswerForm answerForm); + List showAll(Long askId); +} diff --git a/src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java b/src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java new file mode 100644 index 00000000..ba106925 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java @@ -0,0 +1,73 @@ +package project.trendpick_pro.domain.answer.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.answer.entity.Answer; +import project.trendpick_pro.domain.answer.entity.dto.response.AnswerResponse; +import project.trendpick_pro.domain.answer.entity.form.AnswerForm; +import project.trendpick_pro.domain.answer.repository.AnswerRepository; +import project.trendpick_pro.domain.ask.entity.Ask; +import project.trendpick_pro.domain.ask.repository.AskRepository; +import project.trendpick_pro.domain.member.entity.Member; +import project.trendpick_pro.global.rsData.RsData; + +import java.util.List; +import java.util.Objects; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class AnswerServiceImpl implements AnswerService{ + private final AnswerRepository answerRepository; + private final AskRepository askRepository; + + @Transactional + public RsData register(Member member, Long askId, AnswerForm answerForm) { + Ask ask = askRepository.findById(askId).orElseThrow( + () -> new IllegalArgumentException("해당 문의는 없는 문의입니다.") + ); + if (!member.getBrand().equals(ask.getProduct().getBrand().getName())) + return RsData.of("F-1", "타 브랜드 상품에 대한 문의글에는 답변 권한이 없습니다."); + + Answer answer = Answer.write(answerForm); + answer.connectAsk(ask); + answerRepository.save(answer); + return RsData.of("S-1", "답변이 성공적으로 등록되었습니다.", ask.getId()); + } + + @Transactional + public RsData delete(Member member, Long answerId) { + Answer answer = answerRepository.findById(answerId).orElseThrow( + () -> new IllegalArgumentException("해당 답변은 없는 답변입니다.") + ); + + if(!answer.getAsk().getProduct().getBrand().equals(member.getBrand())) + return RsData.of("F-1", "접근 권한이 없습니다."); + + Ask ask = answer.getAsk(); + ask.getAnswerList().remove(answer); + if(ask.getAnswerList().size() == 0) + ask.changeStatusYet(); + + return RsData.of("S-1", "답변이 삭제되었습니다.", answer.getAsk().getId()); + } + + public RsData modify(Member member, Long answerId, AnswerForm answerForm) { + Answer answer = answerRepository.findById(answerId).orElseThrow( + () -> new IllegalArgumentException("해당 답변은 없는 답변입니다.") + ); + + if(!Objects.equals(answer.getAsk().getAuthor().getBrand(), member.getBrand())) + return RsData.of("F-1", "접근 권한이 없습니다."); + answer.update(answerForm); + + return RsData.of("S-1", "답변이 수정되었습니다.", answer.getAsk().getId()); + } + + public List showAll(Long askId) { + List answers = answerRepository.findAllByAskId(askRepository.findById(askId).get()); + return AnswerResponse.of(answers); + } +} + diff --git a/src/main/java/project/trendpick_pro/domain/category/service/MainCategoryService.java b/src/main/java/project/trendpick_pro/domain/category/service/MainCategoryService.java index e3ef537b..141df4a2 100644 --- a/src/main/java/project/trendpick_pro/domain/category/service/MainCategoryService.java +++ b/src/main/java/project/trendpick_pro/domain/category/service/MainCategoryService.java @@ -1,56 +1,17 @@ package project.trendpick_pro.domain.category.service; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import project.trendpick_pro.domain.category.entity.MainCategory; import project.trendpick_pro.domain.category.entity.dto.response.MainCategoryResponse; -import project.trendpick_pro.domain.category.repository.MainCategoryRepository; -import java.util.ArrayList; import java.util.List; -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class MainCategoryService { - private final MainCategoryRepository mainCategoryRepository; - - @Transactional - public void save(String name) { - mainCategoryRepository.save(new MainCategory(name)); - } - - @Transactional - public void saveAll(List name) { - List list = new ArrayList<>(); - for (String s : name) { - list.add(new MainCategory(s)); - } - mainCategoryRepository.saveAll(list); - } - - @Transactional - public void delete(Long id) { - MainCategory mainCategory = mainCategoryRepository.findById(id).orElseThrow(); - mainCategoryRepository.delete(mainCategory); - } - - public List findAll() { - return mainCategoryRepository.findAllBy(); - } - - public MainCategoryResponse findById(Long id) { - MainCategory mainCategory = mainCategoryRepository.findById(id).orElseThrow(); - return new MainCategoryResponse(mainCategory.getName()); - } - - public MainCategory findByBaseId(Long id) { - return mainCategoryRepository.findById(id).orElseThrow(); - } - - public MainCategory findByName(String username) { - return mainCategoryRepository.findByName(username); - } +public interface MainCategoryService { + void save(String name); + void saveAll(List name); + void delete(Long id); + List findAll(); + MainCategoryResponse findById(Long id); + MainCategory findByBaseId(Long id); + MainCategory findByName(String username); } \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/domain/category/service/MainCategoryServiceImpl.java b/src/main/java/project/trendpick_pro/domain/category/service/MainCategoryServiceImpl.java new file mode 100644 index 00000000..def3912b --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/category/service/MainCategoryServiceImpl.java @@ -0,0 +1,56 @@ +package project.trendpick_pro.domain.category.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.category.entity.MainCategory; +import project.trendpick_pro.domain.category.entity.dto.response.MainCategoryResponse; +import project.trendpick_pro.domain.category.repository.MainCategoryRepository; + +import java.util.ArrayList; +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class MainCategoryServiceImpl implements MainCategoryService{ + + private final MainCategoryRepository mainCategoryRepository; + + @Transactional + public void save(String name) { + mainCategoryRepository.save(new MainCategory(name)); + } + + @Transactional + public void saveAll(List name) { + List list = new ArrayList<>(); + for (String s : name) { + list.add(new MainCategory(s)); + } + mainCategoryRepository.saveAll(list); + } + + @Transactional + public void delete(Long id) { + MainCategory mainCategory = mainCategoryRepository.findById(id).orElseThrow(); + mainCategoryRepository.delete(mainCategory); + } + + public List findAll() { + return mainCategoryRepository.findAllBy(); + } + + public MainCategoryResponse findById(Long id) { + MainCategory mainCategory = mainCategoryRepository.findById(id).orElseThrow(); + return new MainCategoryResponse(mainCategory.getName()); + } + + public MainCategory findByBaseId(Long id) { + return mainCategoryRepository.findById(id).orElseThrow(); + } + + public MainCategory findByName(String username) { + return mainCategoryRepository.findByName(username); + } +} diff --git a/src/main/java/project/trendpick_pro/domain/category/service/SubCategoryService.java b/src/main/java/project/trendpick_pro/domain/category/service/SubCategoryService.java index c8cc7590..ec97126e 100644 --- a/src/main/java/project/trendpick_pro/domain/category/service/SubCategoryService.java +++ b/src/main/java/project/trendpick_pro/domain/category/service/SubCategoryService.java @@ -14,52 +14,13 @@ ; -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class SubCategoryService { - private final SubCategoryRepository subCategoryRepository; - - @Transactional - public void save(String name, MainCategory mainCategory){ - subCategoryRepository.save(new SubCategory(name, mainCategory)); - } - - @Transactional - public void saveAll(List name, MainCategory mainCategory){ - List list = new ArrayList<>(); - for (String s : name) { - list.add(new SubCategory(s, mainCategory)); - } - subCategoryRepository.saveAll(list); - } - - @Transactional - public void delete(Long id){ - SubCategory subCategory = subCategoryRepository.findById(id).orElseThrow(); - subCategoryRepository.delete(subCategory); - } - public List findAll(String mainCategoryName) { - if (mainCategoryName.equals("전체")){ - List categories = subCategoryRepository.findAllBy(); - return categories.stream().map(subCategory -> new SubCategoryResponse(subCategory.getName())).toList(); - } else { - List categories = subCategoryRepository.findAllByMainCategory(mainCategoryName); - return categories.stream().map(subCategory -> new SubCategoryResponse(subCategory.getName())).toList(); - } - } - - public SubCategoryResponse findById(Long id){ - SubCategory subCategory = subCategoryRepository.findById(id).orElseThrow(); - return new SubCategoryResponse(subCategory.getName()); - } - - public SubCategory findByBaseId(Long id, MainCategory mainCategory){ - return subCategoryRepository.findByIdInMainCategory(id, mainCategory); - } - - public SubCategory findByName(String username){ - return subCategoryRepository.findByName(username); - } +public interface SubCategoryService { + void save(String name, MainCategory mainCategory); + void saveAll(List name, MainCategory mainCategory); + void delete(Long id); + List findAll(String mainCategoryName); + SubCategoryResponse findById(Long id); + SubCategory findByBaseId(Long id, MainCategory mainCategory); + SubCategory findByName(String username); } \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/domain/category/service/SubCategoryServiceImpl.java b/src/main/java/project/trendpick_pro/domain/category/service/SubCategoryServiceImpl.java new file mode 100644 index 00000000..123772c4 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/category/service/SubCategoryServiceImpl.java @@ -0,0 +1,62 @@ +package project.trendpick_pro.domain.category.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.category.entity.MainCategory; +import project.trendpick_pro.domain.category.entity.SubCategory; +import project.trendpick_pro.domain.category.entity.dto.response.SubCategoryResponse; +import project.trendpick_pro.domain.category.repository.SubCategoryRepository; + +import java.util.ArrayList; +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class SubCategoryServiceImpl implements SubCategoryService{ + + private final SubCategoryRepository subCategoryRepository; + + @Transactional + public void save(String name, MainCategory mainCategory){ + subCategoryRepository.save(new SubCategory(name, mainCategory)); + } + + @Transactional + public void saveAll(List name, MainCategory mainCategory){ + List list = new ArrayList<>(); + for (String s : name) { + list.add(new SubCategory(s, mainCategory)); + } + subCategoryRepository.saveAll(list); + } + + @Transactional + public void delete(Long id){ + SubCategory subCategory = subCategoryRepository.findById(id).orElseThrow(); + subCategoryRepository.delete(subCategory); + } + public List findAll(String mainCategoryName) { + if (mainCategoryName.equals("전체")){ + List categories = subCategoryRepository.findAllBy(); + return categories.stream().map(subCategory -> new SubCategoryResponse(subCategory.getName())).toList(); + } else { + List categories = subCategoryRepository.findAllByMainCategory(mainCategoryName); + return categories.stream().map(subCategory -> new SubCategoryResponse(subCategory.getName())).toList(); + } + } + + public SubCategoryResponse findById(Long id){ + SubCategory subCategory = subCategoryRepository.findById(id).orElseThrow(); + return new SubCategoryResponse(subCategory.getName()); + } + + public SubCategory findByBaseId(Long id, MainCategory mainCategory){ + return subCategoryRepository.findByIdInMainCategory(id, mainCategory); + } + + public SubCategory findByName(String username){ + return subCategoryRepository.findByName(username); + } +} diff --git a/src/main/java/project/trendpick_pro/domain/recommend/service/RecommendService.java b/src/main/java/project/trendpick_pro/domain/recommend/service/RecommendService.java index efd0abc0..9d4379cf 100644 --- a/src/main/java/project/trendpick_pro/domain/recommend/service/RecommendService.java +++ b/src/main/java/project/trendpick_pro/domain/recommend/service/RecommendService.java @@ -1,65 +1,10 @@ package project.trendpick_pro.domain.recommend.service; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import project.trendpick_pro.domain.member.entity.Member; -import project.trendpick_pro.domain.member.exception.MemberNotFoundException; -import project.trendpick_pro.domain.member.repository.MemberRepository; -import project.trendpick_pro.domain.product.entity.product.Product; import project.trendpick_pro.domain.product.entity.product.dto.response.ProductListResponse; -import project.trendpick_pro.domain.product.service.ProductService; -import project.trendpick_pro.domain.recommend.entity.Recommend; -import project.trendpick_pro.domain.recommend.repository.RecommendRepository; -import java.util.List; - -@Slf4j -@Service -@RequiredArgsConstructor -public class RecommendService { - - private final RecommendRepository recommendRepository; - private final ProductService productService; - private final MemberRepository memberRepository; - - @Transactional - @CacheEvict(value = "recommendedProducts", allEntries = true) - public void select(String username){ - - Member member = memberRepository.findByEmail(username).orElseThrow(() -> new MemberNotFoundException("존재하지 않는 회원입니다.")); - - recommendRepository.deleteAllByMemberId(member.getId()); - - List products = productService.getRecommendProduct(member); - - for (Product product : products) { - Recommend recommend = Recommend.of(product); - recommend.connectMember(member); - recommendRepository.save(recommend); - } - } - - @Transactional(readOnly = true) - @Cacheable(value = "recommendedProducts", key = "#member.username + '_' + #offset") - public Page getFindAll(Member member, int offset){ - PageRequest pageable = PageRequest.of(offset, 18); - Page listResponses = recommendRepository.findAllByMemberName(member.getUsername(), pageable); - - List list = listResponses.getContent().stream() - .peek(product -> { - String updatedMainFile = product.getMainFile(); - product.setMainFile(updatedMainFile); - }).toList(); - - return new PageImpl<>(list, pageable, listResponses.getTotalElements()); - } +public interface RecommendService { + void select(String username); + Page getFindAll(Member member, int offset); } diff --git a/src/main/java/project/trendpick_pro/domain/recommend/service/RecommendServiceImpl.java b/src/main/java/project/trendpick_pro/domain/recommend/service/RecommendServiceImpl.java new file mode 100644 index 00000000..87eb118a --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/recommend/service/RecommendServiceImpl.java @@ -0,0 +1,62 @@ +package project.trendpick_pro.domain.recommend.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.member.entity.Member; +import project.trendpick_pro.domain.member.exception.MemberNotFoundException; +import project.trendpick_pro.domain.member.repository.MemberRepository; +import project.trendpick_pro.domain.product.entity.product.Product; +import project.trendpick_pro.domain.product.entity.product.dto.response.ProductListResponse; +import project.trendpick_pro.domain.product.service.ProductService; +import project.trendpick_pro.domain.recommend.entity.Recommend; +import project.trendpick_pro.domain.recommend.repository.RecommendRepository; + +import java.util.List; + +@Slf4j +@Service +@RequiredArgsConstructor +public class RecommendServiceImpl implements RecommendService{ + private final RecommendRepository recommendRepository; + private final ProductService productService; + private final MemberRepository memberRepository; + + @Transactional + @CacheEvict(value = "recommendedProducts", allEntries = true) + public void select(String username){ + + Member member = memberRepository.findByEmail(username).orElseThrow(() -> new MemberNotFoundException("존재하지 않는 회원입니다.")); + + recommendRepository.deleteAllByMemberId(member.getId()); + + List products = productService.getRecommendProduct(member); + + for (Product product : products) { + Recommend recommend = Recommend.of(product); + recommend.connectMember(member); + recommendRepository.save(recommend); + } + } + + @Transactional(readOnly = true) + @Cacheable(value = "recommendedProducts", key = "#member.username + '_' + #offset") + public Page getFindAll(Member member, int offset){ + PageRequest pageable = PageRequest.of(offset, 18); + Page listResponses = recommendRepository.findAllByMemberName(member.getUsername(), pageable); + + List list = listResponses.getContent().stream() + .peek(product -> { + String updatedMainFile = product.getMainFile(); + product.setMainFile(updatedMainFile); + }).toList(); + + return new PageImpl<>(list, pageable, listResponses.getTotalElements()); + } +} diff --git a/src/main/java/project/trendpick_pro/domain/review/service/ReviewService.java b/src/main/java/project/trendpick_pro/domain/review/service/ReviewService.java index 00671f6f..31465a00 100644 --- a/src/main/java/project/trendpick_pro/domain/review/service/ReviewService.java +++ b/src/main/java/project/trendpick_pro/domain/review/service/ReviewService.java @@ -26,95 +26,14 @@ import java.util.List; -@Service -@Transactional(readOnly = true) -@RequiredArgsConstructor -public class ReviewService { - private final ReviewRepository reviewRepository; - private final ProductRepository productRepository; - private final FileTranslator fileTranslator; - private final Rq rq; - - private final AmazonS3 amazonS3; - - @Value("${cloud.aws.s3.bucket}") - private String bucket; - - @Value("https://kr.object.ncloudstorage.com/{cloud.aws.s3.bucket}/") - private String filePath; - - public ReviewResponse showReview(Long productId) { - Review review = reviewRepository.findById(productId).orElseThrow(); - - return ReviewResponse.of(review); - } - - public Review findById(Long id) { - return reviewRepository.findById(id).orElseThrow(); - } - - public Page getProductReviews(Long productId, Pageable pageable) { - pageable = PageRequest.of(pageable.getPageNumber(), 6); - return reviewRepository.findAllByProductId(productId, pageable); - } - - @Transactional - public RsData createReview(Member actor, Long productId, ReviewSaveRequest reviewSaveRequest, MultipartFile requestMainFile, List requestSubFiles) throws Exception { - Product product = productRepository.findById(productId).orElseThrow(); - - CommonFile mainFile = fileTranslator.translateFile(requestMainFile); - List subFiles = fileTranslator.translateFileList(requestSubFiles); - - for (CommonFile subFile : subFiles) { - mainFile.connectFile(subFile); - } - - Review review = Review.of(reviewSaveRequest, actor, product, mainFile); - product.addReview(review.getRating()); //상품 리뷰수, 상품 평균 평점을 계산해서 저장 - reviewRepository.save(review); - - return RsData.of("S-1", "리뷰 등록이 완료되었습니다.", ReviewResponse.of(review)); - } - - @Transactional - public RsData modify(Long reviewId, ReviewSaveRequest reviewSaveRequest, MultipartFile requestMainFile, List requestSubFiles) throws IOException { - Review review = reviewRepository.findById(reviewId).orElseThrow(); - - review.getFile().deleteFile(amazonS3, bucket); - review.disconnectFile(); - - CommonFile mainFile = fileTranslator.translateFile(requestMainFile); - List subFiles = fileTranslator.translateFileList(requestSubFiles); - - for (CommonFile subFile : subFiles) { - mainFile.connectFile(subFile); - } - - review.update(reviewSaveRequest, mainFile); - - return RsData.of("S-1", "리뷰 수정이 완료되었습니다.", ReviewResponse.of(review)); - } - - @Transactional - public void delete(Long reviewId) { - rq.getAdmin(); - Review review = reviewRepository.findById(reviewId).orElseThrow(); - review.getFile().deleteFile(amazonS3, bucket); - reviewRepository.delete(review); - } - - @Transactional - public Page showAll(Pageable pageable) { - pageable = PageRequest.of(pageable.getPageNumber(), 6); - Page reviewPage = reviewRepository.findAll(pageable); - return reviewPage.map(ReviewResponse::of); - } - - @Transactional - public Page showOwnReview(String writer, Pageable pageable) { - pageable = PageRequest.of(pageable.getPageNumber(), 6); - Page reviewPage = reviewRepository.findByWriter(writer, pageable); - return reviewPage.map(ReviewResponse::of); - } +public interface ReviewService { + ReviewResponse showReview(Long productId); + Review findById(Long id); + Page getProductReviews(Long productId, Pageable pageable); + RsData createReview(Member actor, Long productId, ReviewSaveRequest reviewSaveRequest, MultipartFile requestMainFile, List requestSubFiles) throws Exception; + RsData modify(Long reviewId, ReviewSaveRequest reviewSaveRequest, MultipartFile requestMainFile, List requestSubFiles) throws IOException; + void delete(Long reviewId); + Page showAll(Pageable pageable); + Page showOwnReview(String writer, Pageable pageable); } diff --git a/src/main/java/project/trendpick_pro/domain/review/service/ReviewServiceImpl.java b/src/main/java/project/trendpick_pro/domain/review/service/ReviewServiceImpl.java new file mode 100644 index 00000000..5d8a3e6d --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/review/service/ReviewServiceImpl.java @@ -0,0 +1,119 @@ +package project.trendpick_pro.domain.review.service; + +import com.amazonaws.services.s3.AmazonS3; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import project.trendpick_pro.domain.common.base.filetranslator.FileTranslator; +import project.trendpick_pro.domain.common.base.rq.Rq; +import project.trendpick_pro.domain.common.file.CommonFile; +import project.trendpick_pro.domain.member.entity.Member; +import project.trendpick_pro.domain.product.entity.product.Product; +import project.trendpick_pro.domain.product.repository.ProductRepository; +import project.trendpick_pro.domain.review.entity.Review; +import project.trendpick_pro.domain.review.entity.dto.request.ReviewSaveRequest; +import project.trendpick_pro.domain.review.entity.dto.response.ReviewProductResponse; +import project.trendpick_pro.domain.review.entity.dto.response.ReviewResponse; +import project.trendpick_pro.domain.review.repository.ReviewRepository; +import project.trendpick_pro.global.rsData.RsData; + +import java.io.IOException; +import java.util.List; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class ReviewServiceImpl implements ReviewService{ + private final ReviewRepository reviewRepository; + private final ProductRepository productRepository; + private final FileTranslator fileTranslator; + + private final Rq rq; + + private final AmazonS3 amazonS3; + + @Value("${cloud.aws.s3.bucket}") + private String bucket; + + @Value("https://kr.object.ncloudstorage.com/{cloud.aws.s3.bucket}/") + private String filePath; + + public ReviewResponse showReview(Long productId) { + Review review = reviewRepository.findById(productId).orElseThrow(); + + return ReviewResponse.of(review); + } + + public Review findById(Long id) { + return reviewRepository.findById(id).orElseThrow(); + } + + public Page getProductReviews(Long productId, Pageable pageable) { + pageable = PageRequest.of(pageable.getPageNumber(), 6); + return reviewRepository.findAllByProductId(productId, pageable); + } + + @Transactional + public RsData createReview(Member actor, Long productId, ReviewSaveRequest reviewSaveRequest, MultipartFile requestMainFile, List requestSubFiles) throws Exception { + Product product = productRepository.findById(productId).orElseThrow(); + + CommonFile mainFile = fileTranslator.translateFile(requestMainFile); + List subFiles = fileTranslator.translateFileList(requestSubFiles); + + for (CommonFile subFile : subFiles) { + mainFile.connectFile(subFile); + } + + Review review = Review.of(reviewSaveRequest, actor, product, mainFile); + product.addReview(review.getRating()); //상품 리뷰수, 상품 평균 평점을 계산해서 저장 + reviewRepository.save(review); + + return RsData.of("S-1", "리뷰 등록이 완료되었습니다.", ReviewResponse.of(review)); + } + + @Transactional + public RsData modify(Long reviewId, ReviewSaveRequest reviewSaveRequest, MultipartFile requestMainFile, List requestSubFiles) throws IOException { + Review review = reviewRepository.findById(reviewId).orElseThrow(); + + review.getFile().deleteFile(amazonS3, bucket); + review.disconnectFile(); + + CommonFile mainFile = fileTranslator.translateFile(requestMainFile); + List subFiles = fileTranslator.translateFileList(requestSubFiles); + + for (CommonFile subFile : subFiles) { + mainFile.connectFile(subFile); + } + + review.update(reviewSaveRequest, mainFile); + + return RsData.of("S-1", "리뷰 수정이 완료되었습니다.", ReviewResponse.of(review)); + } + + @Transactional + public void delete(Long reviewId) { + rq.getAdmin(); + Review review = reviewRepository.findById(reviewId).orElseThrow(); + review.getFile().deleteFile(amazonS3, bucket); + reviewRepository.delete(review); + } + + @Transactional + public Page showAll(Pageable pageable) { + pageable = PageRequest.of(pageable.getPageNumber(), 6); + Page reviewPage = reviewRepository.findAll(pageable); + return reviewPage.map(ReviewResponse::of); + } + + @Transactional + public Page showOwnReview(String writer, Pageable pageable) { + pageable = PageRequest.of(pageable.getPageNumber(), 6); + Page reviewPage = reviewRepository.findByWriter(writer, pageable); + return reviewPage.map(ReviewResponse::of); + } +} diff --git a/src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentService.java b/src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentService.java index b59dcf9f..991a905f 100644 --- a/src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentService.java +++ b/src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentService.java @@ -1,63 +1,8 @@ package project.trendpick_pro.global.tosspayment.service; -import net.minidev.json.JSONObject; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; import project.trendpick_pro.global.tosspayment.dto.PaymentResultResponse; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.Collections; - -@Service -public class PaymentService { - - @Value("${toss.secretKey}") - private String secretKey; - - @Value("${toss.url}") - private String tossURL; - - public PaymentResultResponse requestPayment(String paymentKey, String orderId, Integer amount) { - RestTemplate restTemplate = new RestTemplate(); - HttpHeaders headers = new HttpHeaders(); - String secret = new String(Base64.getEncoder().encode((secretKey + ":").getBytes(StandardCharsets.UTF_8))); - - headers.setBasicAuth(secret); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); - - JSONObject params = new JSONObject(); - params.put("orderId", orderId); - params.put("amount", String.valueOf(amount)); - - return restTemplate.postForEntity(tossURL + paymentKey, new HttpEntity<>(params, headers), PaymentResultResponse.class).getBody(); - } - - public void cancelPayment(String paymentKey) { - - URI uri = URI.create(tossURL + paymentKey + "/cancel"); - - RestTemplate restTemplate = new RestTemplate(); - HttpHeaders headers = new HttpHeaders(); - String secret = new String(Base64.getEncoder().encode((secretKey + ":").getBytes(StandardCharsets.UTF_8))); - - headers.setBasicAuth(secret); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); - - JSONObject params = new JSONObject(); - params.put("cancelReason", "단순 변심"); - - restTemplate.postForObject( - uri, - new HttpEntity<>(params, headers), - PaymentResultResponse.class - ); - } +public interface PaymentService { + PaymentResultResponse requestPayment(String paymentKey, String orderId, Integer amount); + void cancelPayment(String paymentKey); } \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentServiceImpl.java b/src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentServiceImpl.java new file mode 100644 index 00000000..53fd2b0b --- /dev/null +++ b/src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentServiceImpl.java @@ -0,0 +1,63 @@ +package project.trendpick_pro.global.tosspayment.service; + +import net.minidev.json.JSONObject; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; +import project.trendpick_pro.global.tosspayment.dto.PaymentResultResponse; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Collections; + +@Service +public class PaymentServiceImpl implements PaymentService{ + + @Value("${toss.secretKey}") + private String secretKey; + + @Value("${toss.url}") + private String tossURL; + + public PaymentResultResponse requestPayment(String paymentKey, String orderId, Integer amount) { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + String secret = new String(Base64.getEncoder().encode((secretKey + ":").getBytes(StandardCharsets.UTF_8))); + + headers.setBasicAuth(secret); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + + JSONObject params = new JSONObject(); + params.put("orderId", orderId); + params.put("amount", String.valueOf(amount)); + + return restTemplate.postForEntity(tossURL + paymentKey, new HttpEntity<>(params, headers), PaymentResultResponse.class).getBody(); + } + + public void cancelPayment(String paymentKey) { + + URI uri = URI.create(tossURL + paymentKey + "/cancel"); + + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + String secret = new String(Base64.getEncoder().encode((secretKey + ":").getBytes(StandardCharsets.UTF_8))); + + headers.setBasicAuth(secret); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + + JSONObject params = new JSONObject(); + params.put("cancelReason", "단순 변심"); + + restTemplate.postForObject( + uri, + new HttpEntity<>(params, headers), + PaymentResultResponse.class + ); + } +} From d3ebfeabfc93c9bf25f971b0556c0dbecc4aa1e0 Mon Sep 17 00:00:00 2001 From: hye-0000 Date: Mon, 10 Jul 2023 15:05:57 +0900 Subject: [PATCH 02/26] =?UTF-8?q?refactor:=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IllegalArgumentException(잘못된 인수를 전달했을 때 사용)에서 NoSuchElementException(요소를 찾지 못했을 때 발생하는 예외)로 변경 --- .../domain/answer/service/AnswerServiceImpl.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java b/src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java index ba106925..6c64c175 100644 --- a/src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java +++ b/src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java @@ -13,6 +13,7 @@ import project.trendpick_pro.global.rsData.RsData; import java.util.List; +import java.util.NoSuchElementException; import java.util.Objects; @Service @@ -25,7 +26,7 @@ public class AnswerServiceImpl implements AnswerService{ @Transactional public RsData register(Member member, Long askId, AnswerForm answerForm) { Ask ask = askRepository.findById(askId).orElseThrow( - () -> new IllegalArgumentException("해당 문의는 없는 문의입니다.") + () -> new NoSuchElementException("해당 문의는 없는 문의입니다.") ); if (!member.getBrand().equals(ask.getProduct().getBrand().getName())) return RsData.of("F-1", "타 브랜드 상품에 대한 문의글에는 답변 권한이 없습니다."); @@ -39,7 +40,7 @@ public RsData register(Member member, Long askId, AnswerForm answerForm) { @Transactional public RsData delete(Member member, Long answerId) { Answer answer = answerRepository.findById(answerId).orElseThrow( - () -> new IllegalArgumentException("해당 답변은 없는 답변입니다.") + () -> new NoSuchElementException("해당 답변은 없는 답변입니다.") ); if(!answer.getAsk().getProduct().getBrand().equals(member.getBrand())) @@ -55,7 +56,7 @@ public RsData delete(Member member, Long answerId) { public RsData modify(Member member, Long answerId, AnswerForm answerForm) { Answer answer = answerRepository.findById(answerId).orElseThrow( - () -> new IllegalArgumentException("해당 답변은 없는 답변입니다.") + () -> new NoSuchElementException("해당 답변은 없는 답변입니다.") ); if(!Objects.equals(answer.getAsk().getAuthor().getBrand(), member.getBrand())) From bbb0a03dff2fef2fa0a7b114c6ca2f845b00ca49 Mon Sep 17 00:00:00 2001 From: mmunkyeong Date: Mon, 10 Jul 2023 15:25:23 +0900 Subject: [PATCH 03/26] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20evenType=20=EC=82=AD=EC=A0=9C=20(#354)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../project/trendpick_pro/domain/cash/entity/CashLog.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/project/trendpick_pro/domain/cash/entity/CashLog.java b/src/main/java/project/trendpick_pro/domain/cash/entity/CashLog.java index 7faeff5a..07ba24a4 100644 --- a/src/main/java/project/trendpick_pro/domain/cash/entity/CashLog.java +++ b/src/main/java/project/trendpick_pro/domain/cash/entity/CashLog.java @@ -36,12 +36,7 @@ public CashLog(Long id){ this.id=id; } public enum EvenType { - 충전__무통장입금, - 충전__토스페이먼츠, 출금__통장입금, - 사용__토스페이먼츠_주문결제, - 사용__예치금_주문결제, - 환불__예치금_주문결제, 브랜드정산__예치금; } } \ No newline at end of file From 11671a2175bff27a4725107712d7915607ec039e Mon Sep 17 00:00:00 2001 From: hye-0000 Date: Mon, 10 Jul 2023 15:27:50 +0900 Subject: [PATCH 04/26] =?UTF-8?q?refactor:=20@Transactional=20=EC=96=B4?= =?UTF-8?q?=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trendpick_pro/domain/answer/service/AnswerServiceImpl.java | 3 ++- .../domain/category/service/MainCategoryServiceImpl.java | 1 - .../domain/category/service/SubCategoryServiceImpl.java | 2 +- .../domain/recommend/service/RecommendServiceImpl.java | 1 - .../trendpick_pro/domain/review/service/ReviewServiceImpl.java | 1 - 5 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java b/src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java index 6c64c175..11cd09cf 100644 --- a/src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java +++ b/src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java @@ -17,7 +17,6 @@ import java.util.Objects; @Service -@Transactional(readOnly = true) @RequiredArgsConstructor public class AnswerServiceImpl implements AnswerService{ private final AnswerRepository answerRepository; @@ -54,6 +53,7 @@ public RsData delete(Member member, Long answerId) { return RsData.of("S-1", "답변이 삭제되었습니다.", answer.getAsk().getId()); } + @Transactional public RsData modify(Member member, Long answerId, AnswerForm answerForm) { Answer answer = answerRepository.findById(answerId).orElseThrow( () -> new NoSuchElementException("해당 답변은 없는 답변입니다.") @@ -66,6 +66,7 @@ public RsData modify(Member member, Long answerId, AnswerForm answerForm) return RsData.of("S-1", "답변이 수정되었습니다.", answer.getAsk().getId()); } + @Transactional public List showAll(Long askId) { List answers = answerRepository.findAllByAskId(askRepository.findById(askId).get()); return AnswerResponse.of(answers); diff --git a/src/main/java/project/trendpick_pro/domain/category/service/MainCategoryServiceImpl.java b/src/main/java/project/trendpick_pro/domain/category/service/MainCategoryServiceImpl.java index def3912b..8c978487 100644 --- a/src/main/java/project/trendpick_pro/domain/category/service/MainCategoryServiceImpl.java +++ b/src/main/java/project/trendpick_pro/domain/category/service/MainCategoryServiceImpl.java @@ -12,7 +12,6 @@ @Service @RequiredArgsConstructor -@Transactional(readOnly = true) public class MainCategoryServiceImpl implements MainCategoryService{ private final MainCategoryRepository mainCategoryRepository; diff --git a/src/main/java/project/trendpick_pro/domain/category/service/SubCategoryServiceImpl.java b/src/main/java/project/trendpick_pro/domain/category/service/SubCategoryServiceImpl.java index 123772c4..f330d496 100644 --- a/src/main/java/project/trendpick_pro/domain/category/service/SubCategoryServiceImpl.java +++ b/src/main/java/project/trendpick_pro/domain/category/service/SubCategoryServiceImpl.java @@ -13,7 +13,6 @@ @Service @RequiredArgsConstructor -@Transactional(readOnly = true) public class SubCategoryServiceImpl implements SubCategoryService{ private final SubCategoryRepository subCategoryRepository; @@ -37,6 +36,7 @@ public void delete(Long id){ SubCategory subCategory = subCategoryRepository.findById(id).orElseThrow(); subCategoryRepository.delete(subCategory); } + public List findAll(String mainCategoryName) { if (mainCategoryName.equals("전체")){ List categories = subCategoryRepository.findAllBy(); diff --git a/src/main/java/project/trendpick_pro/domain/recommend/service/RecommendServiceImpl.java b/src/main/java/project/trendpick_pro/domain/recommend/service/RecommendServiceImpl.java index 87eb118a..b51833d6 100644 --- a/src/main/java/project/trendpick_pro/domain/recommend/service/RecommendServiceImpl.java +++ b/src/main/java/project/trendpick_pro/domain/recommend/service/RecommendServiceImpl.java @@ -45,7 +45,6 @@ public void select(String username){ } } - @Transactional(readOnly = true) @Cacheable(value = "recommendedProducts", key = "#member.username + '_' + #offset") public Page getFindAll(Member member, int offset){ PageRequest pageable = PageRequest.of(offset, 18); diff --git a/src/main/java/project/trendpick_pro/domain/review/service/ReviewServiceImpl.java b/src/main/java/project/trendpick_pro/domain/review/service/ReviewServiceImpl.java index 5d8a3e6d..ad41a723 100644 --- a/src/main/java/project/trendpick_pro/domain/review/service/ReviewServiceImpl.java +++ b/src/main/java/project/trendpick_pro/domain/review/service/ReviewServiceImpl.java @@ -26,7 +26,6 @@ import java.util.List; @Service -@Transactional(readOnly = true) @RequiredArgsConstructor public class ReviewServiceImpl implements ReviewService{ private final ReviewRepository reviewRepository; From 845d66e161f127a1f67032e4d077bf7b4418e200 Mon Sep 17 00:00:00 2001 From: hye-0000 Date: Mon, 10 Jul 2023 15:34:42 +0900 Subject: [PATCH 05/26] =?UTF-8?q?refactor:=20=EB=B0=98=ED=99=98=ED=83=80?= =?UTF-8?q?=EC=9E=85=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EC=A1=B0=EA=B1=B4?= =?UTF-8?q?=EB=AC=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Brand객체와 String을 비교하고 있던 조건문을 String/String 비교가 가능하도록 수정 --- .../trendpick_pro/domain/answer/service/AnswerServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java b/src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java index 11cd09cf..ac266e97 100644 --- a/src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java +++ b/src/main/java/project/trendpick_pro/domain/answer/service/AnswerServiceImpl.java @@ -42,7 +42,7 @@ public RsData delete(Member member, Long answerId) { () -> new NoSuchElementException("해당 답변은 없는 답변입니다.") ); - if(!answer.getAsk().getProduct().getBrand().equals(member.getBrand())) + if(!answer.getAsk().getProduct().getBrand().getName().equals(member.getBrand())) return RsData.of("F-1", "접근 권한이 없습니다."); Ask ask = answer.getAsk(); From c6a6bf2e4daa1046d5f0553bde57340393d1c886 Mon Sep 17 00:00:00 2001 From: jooooonj Date: Mon, 10 Jul 2023 17:23:57 +0900 Subject: [PATCH 06/26] =?UTF-8?q?refactor:=20=EB=B8=8C=EB=9E=9C=EB=93=9C?= =?UTF-8?q?=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=EA=B5=AC=EC=A1=B0=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81(#353)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/brand/service/BrandService.java | 53 +++------------ .../brand/service/BrandServiceImpl.java | 64 +++++++++++++++++++ 2 files changed, 72 insertions(+), 45 deletions(-) create mode 100644 src/main/java/project/trendpick_pro/domain/brand/service/BrandServiceImpl.java diff --git a/src/main/java/project/trendpick_pro/domain/brand/service/BrandService.java b/src/main/java/project/trendpick_pro/domain/brand/service/BrandService.java index 447c37b6..a84a973b 100644 --- a/src/main/java/project/trendpick_pro/domain/brand/service/BrandService.java +++ b/src/main/java/project/trendpick_pro/domain/brand/service/BrandService.java @@ -1,53 +1,16 @@ package project.trendpick_pro.domain.brand.service; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import project.trendpick_pro.domain.brand.entity.Brand; import project.trendpick_pro.domain.brand.entity.dto.BrandResponse; -import project.trendpick_pro.domain.brand.repository.BrandRepository; import java.util.List; -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class BrandService { - - private final BrandRepository brandRepository; - - public boolean isPresent(String name){ - return brandRepository.findByName(name).isPresent(); - } - - @Transactional - public void save(String name){ - brandRepository.save(new Brand(name)); - } - - @Transactional - public void delete(Long id){ - Brand brand = brandRepository.findById(id).orElseThrow(); - brandRepository.delete(brand); - } - - public List findAll(){ - return brandRepository.findAllBy(); - } - - public Brand findByName(String name) { - try { - return brandRepository.findByName(name).get(); - } catch (Exception e) { - return brandRepository.save(new Brand(name)); - } - } - - public Brand findById(Long id) { - return brandRepository.findById(id).orElseThrow(); - } - - public Long count() { - return brandRepository.count(); - } +public interface BrandService { + boolean isPresent(String name); + void save(String name); + void delete(Long id); + List findAll(); + Brand findByName(String name); + Brand findById(Long id); + Long count(); } diff --git a/src/main/java/project/trendpick_pro/domain/brand/service/BrandServiceImpl.java b/src/main/java/project/trendpick_pro/domain/brand/service/BrandServiceImpl.java new file mode 100644 index 00000000..983eccc4 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/brand/service/BrandServiceImpl.java @@ -0,0 +1,64 @@ +package project.trendpick_pro.domain.brand.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.brand.entity.Brand; +import project.trendpick_pro.domain.brand.entity.dto.BrandResponse; +import project.trendpick_pro.domain.brand.repository.BrandRepository; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class BrandServiceImpl implements BrandService{ + + private final BrandRepository brandRepository; + + @Transactional(readOnly = true) + @Override + public boolean isPresent(String name){ + return brandRepository.findByName(name).isPresent(); + } + + @Transactional + @Override + public void save(String name){ + brandRepository.save(new Brand(name)); + } + + @Transactional + @Override + public void delete(Long id){ + Brand brand = brandRepository.findById(id).orElseThrow(); + brandRepository.delete(brand); + } + + @Transactional(readOnly = true) + @Override + public List findAll(){ + return brandRepository.findAllBy(); + } + + @Transactional(readOnly = true) + @Override + public Brand findByName(String name) { + try { + return brandRepository.findByName(name).get(); + } catch (Exception e) { + return brandRepository.save(new Brand(name)); + } + } + + @Transactional(readOnly = true) + @Override + public Brand findById(Long id) { + return brandRepository.findById(id).orElseThrow(); + } + + @Transactional(readOnly = true) + @Override + public Long count() { + return brandRepository.count(); + } +} From 96ccc7259831ed2633c8bf0849a3bce5c1a8b4dd Mon Sep 17 00:00:00 2001 From: jooooonj Date: Mon, 10 Jul 2023 17:25:48 +0900 Subject: [PATCH 07/26] =?UTF-8?q?refactor:=20Cart=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81(#353)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cart/entity/dto/request/CartRequest.java | 9 -- .../cart/repository/CartItemRepository.java | 4 +- .../domain/cart/service/CartService.java | 119 ++-------------- .../domain/cart/service/CartServiceImpl.java | 128 ++++++++++++++++++ .../domain/coupon/service/CouponService.java | 1 - 5 files changed, 138 insertions(+), 123 deletions(-) delete mode 100644 src/main/java/project/trendpick_pro/domain/cart/entity/dto/request/CartRequest.java create mode 100644 src/main/java/project/trendpick_pro/domain/cart/service/CartServiceImpl.java diff --git a/src/main/java/project/trendpick_pro/domain/cart/entity/dto/request/CartRequest.java b/src/main/java/project/trendpick_pro/domain/cart/entity/dto/request/CartRequest.java deleted file mode 100644 index f5fa3ec9..00000000 --- a/src/main/java/project/trendpick_pro/domain/cart/entity/dto/request/CartRequest.java +++ /dev/null @@ -1,9 +0,0 @@ -package project.trendpick_pro.domain.cart.entity.dto.request; - - -import jakarta.validation.constraints.NotBlank; - -public class CartRequest { - @NotBlank - private Long memberId; -} \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/domain/cart/repository/CartItemRepository.java b/src/main/java/project/trendpick_pro/domain/cart/repository/CartItemRepository.java index e53f0558..a90c9645 100644 --- a/src/main/java/project/trendpick_pro/domain/cart/repository/CartItemRepository.java +++ b/src/main/java/project/trendpick_pro/domain/cart/repository/CartItemRepository.java @@ -1,13 +1,13 @@ package project.trendpick_pro.domain.cart.repository; import org.springframework.data.jpa.repository.JpaRepository; +import project.trendpick_pro.domain.cart.entity.Cart; import project.trendpick_pro.domain.cart.entity.CartItem; import java.util.List; public interface CartItemRepository extends JpaRepository { CartItem findByCartIdAndProductId(Long cartId, long ProductId); - List findByProductId(Long productId); - CartItem findByCartId(Long cartItemID); + List findAllByCart(Cart cart); } diff --git a/src/main/java/project/trendpick_pro/domain/cart/service/CartService.java b/src/main/java/project/trendpick_pro/domain/cart/service/CartService.java index cacec177..9880a329 100644 --- a/src/main/java/project/trendpick_pro/domain/cart/service/CartService.java +++ b/src/main/java/project/trendpick_pro/domain/cart/service/CartService.java @@ -1,125 +1,22 @@ package project.trendpick_pro.domain.cart.service; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import project.trendpick_pro.domain.cart.entity.Cart; import project.trendpick_pro.domain.cart.entity.CartItem; import project.trendpick_pro.domain.cart.entity.dto.request.CartItemRequest; import project.trendpick_pro.domain.cart.entity.dto.response.CartItemResponse; -import project.trendpick_pro.domain.cart.repository.CartItemRepository; -import project.trendpick_pro.domain.cart.repository.CartRepository; import project.trendpick_pro.domain.member.entity.Member; import project.trendpick_pro.domain.orders.entity.Order; import project.trendpick_pro.domain.orders.entity.dto.request.CartToOrderRequest; -import project.trendpick_pro.domain.product.entity.product.Product; -import project.trendpick_pro.domain.product.service.ProductService; -import project.trendpick_pro.domain.tags.favoritetag.service.FavoriteTagService; -import project.trendpick_pro.domain.tags.tag.entity.type.TagType; import project.trendpick_pro.global.rsData.RsData; -import java.util.ArrayList; import java.util.List; -import java.util.Objects; -@Service -@Transactional(readOnly = true) -@RequiredArgsConstructor -public class CartService { - - private final CartRepository cartRepository; - private final CartItemRepository cartItemRepository; - - private final ProductService productService; - private final FavoriteTagService favoriteTagService; - - - // 장바구니 조회 - public List CartView(Cart cart) { - List cartItems = cartItemRepository.findAll(); - List userItems = new ArrayList<>(); - // 장바구니가 비어있는 경우 - if (cart == null) { - return userItems; - } - for (CartItem cartItem : cartItems) { - if (Objects.equals(cartItem.getCart().getId(), cart.getId())) { - userItems.add(cartItem); - } - } - return userItems; - } - - // 장바구니 상품 추가 - @Transactional - public RsData addItemToCart(Member member, CartItemRequest cartItemRequest) { - - Cart cart = cartRepository.findByMemberId(member.getId()); - Product product = productService.findById(cartItemRequest.getProductId()); - - if (product == null) { - return RsData.of("F-1", "해당상품을 찾을 수 없습니다."); - } - if (cart == null) { - cart = Cart.createCart(member); - cartRepository.save(cart); - } - - CartItem cartItem = cartItemRepository.findByCartIdAndProductId(cart.getId(), product.getId()); - favoriteTagService.updateTag(member, product, TagType.CART); - - if (cartItem != null) { - cartItem.addCount(cartItemRequest.getQuantity()); - cart.setTotalCount(cart.getTotalCount() + cartItemRequest.getQuantity()); - } else { - cartItem = CartItem.of(cart, product, cartItemRequest); - cart.setTotalCount(cart.getTotalCount() + 1); - cartItemRepository.save(cartItem); - } - - return RsData.of("S-1", "상품이 추가되었습니다.", CartItemResponse.of(cartItem)); - } - - - // 상품을 장바구니에서 제거 - @Transactional - public void removeItemFromCart(Long cartItemId) { - cartItemRepository.deleteById(cartItemId); - } - - // 상품의 수량 업데이트 - @Transactional - public RsData updateItemCount(Long cartItemId, int quantity) { - CartItem cartItem = cartItemRepository.findById(cartItemId).orElse(null); - if (cartItem == null) { - return RsData.of("F-1", "해당 상품은 장바구니에 없습니다."); - } - cartItem.update(quantity); - return RsData.of("S-1", "상품 수량이 업데이트 되었습니다.", cartItem); - } - - public Cart getCartByUser(Long memberId) { - return cartRepository.findByMemberId(memberId); - } - - public List findCartItems(Member member, CartToOrderRequest request) { - Cart cart = getCartByUser(member.getId()); //현재 로그인되어 있는 cart 정보 - List cartItemList = new ArrayList<>(); - - for (Long id : request.getSelectedItems()) { - for (CartItem item : cartItemRepository.findByProductId(id)) { - if (Objects.equals(item.getCart().getId(), cart.getId())) { - cartItemList.add(item); - } - } - } - return cartItemList; - } - - @Transactional - public void deleteCartItemsByOrder(Order order) { - List cartItems = order.getCartItems(); - cartItemRepository.deleteAllInBatch(cartItems); - } +public interface CartService { + List CartView(Cart cart); + RsData addItemToCart(Member member, CartItemRequest cartItemRequest); + RsData updateItemCount(Long cartItemId, int quantity); + void removeItemFromCart(Long cartItemId); + Cart getCartByUser(Long memberId); + void deleteCartItemsByOrder(Order order); + List findCartItems(Member member, CartToOrderRequest request); } - diff --git a/src/main/java/project/trendpick_pro/domain/cart/service/CartServiceImpl.java b/src/main/java/project/trendpick_pro/domain/cart/service/CartServiceImpl.java new file mode 100644 index 00000000..1f6df303 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/cart/service/CartServiceImpl.java @@ -0,0 +1,128 @@ +package project.trendpick_pro.domain.cart.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.cart.entity.Cart; +import project.trendpick_pro.domain.cart.entity.CartItem; +import project.trendpick_pro.domain.cart.entity.dto.request.CartItemRequest; +import project.trendpick_pro.domain.cart.entity.dto.response.CartItemResponse; +import project.trendpick_pro.domain.cart.repository.CartItemRepository; +import project.trendpick_pro.domain.cart.repository.CartRepository; +import project.trendpick_pro.domain.member.entity.Member; +import project.trendpick_pro.domain.orders.entity.Order; +import project.trendpick_pro.domain.orders.entity.dto.request.CartToOrderRequest; +import project.trendpick_pro.domain.product.entity.product.Product; +import project.trendpick_pro.domain.product.service.ProductService; +import project.trendpick_pro.domain.tags.favoritetag.service.FavoriteTagService; +import project.trendpick_pro.domain.tags.type.TagType; +import project.trendpick_pro.global.rsData.RsData; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +@Service +@RequiredArgsConstructor +public class CartServiceImpl implements CartService{ + + private final CartRepository cartRepository; + private final CartItemRepository cartItemRepository; + + private final ProductService productService; + private final FavoriteTagService favoriteTagService; + + @Transactional(readOnly = true) + @Override + // 장바구니 조회 + public List CartView(Cart cart) { + return cartItemRepository.findAllByCart(cart); + } + + // 장바구니 상품 추가 + @Transactional + @Override + public RsData addItemToCart(Member member, CartItemRequest cartItemRequest) { + + Cart cart = cartRepository.findByMemberId(member.getId()); + Product product = productService.findById(cartItemRequest.getProductId()); + + if (product == null) { + return RsData.of("F-1", "해당상품을 찾을 수 없습니다."); + } + + if (cart == null) { + cart = Cart.createCart(member); + cartRepository.save(cart); + } + + CartItem cartItem = cartItemRepository.findByCartIdAndProductId(cart.getId(), product.getId()); + + if (cartItem != null) { + cartItem.addCount(cartItemRequest.getQuantity()); + cart.setTotalCount(cart.getTotalCount() + 1); + } else { + cartItem = CartItem.of(cart, product, cartItemRequest); + cart.setTotalCount(cart.getTotalCount() + 1); + cartItemRepository.save(cartItem); + } + + favoriteTagService.updateTag(member, product, TagType.CART); + return RsData.of("S-1", "상품이 추가되었습니다.", CartItemResponse.of(cartItem)); + } + + + // 상품을 장바구니에서 제거 + @Transactional + @Override + public void removeItemFromCart(Long cartItemId) { + CartItem cartItem = cartItemRepository.findById(cartItemId).orElse(null); + if(cartItem != null){ + Cart cart = cartItem.getCart(); + cart.setTotalCount(cart.getTotalCount() - 1); + } + cartItemRepository.deleteById(cartItemId); + } + + // 상품의 수량 업데이트 + @Transactional + @Override + public RsData updateItemCount(Long cartItemId, int quantity) { + CartItem cartItem = cartItemRepository.findById(cartItemId).orElse(null); + if (cartItem == null) { + return RsData.of("F-1", "해당 상품은 장바구니에 없습니다."); + } + cartItem.update(quantity); + return RsData.of("S-1", "상품 수량이 업데이트 되었습니다.", cartItem); + } + + @Override + @Transactional(readOnly = true) + public Cart getCartByUser(Long memberId) { + return cartRepository.findByMemberId(memberId); + } + + @Transactional(readOnly = true) + @Override + public List findCartItems(Member member, CartToOrderRequest request) { + Cart cart = getCartByUser(member.getId()); //현재 로그인되어 있는 cart 정보 + List cartItemList = new ArrayList<>(); + + for (Long id : request.getSelectedItems()) { + for (CartItem item : cartItemRepository.findByProductId(id)) { + if (Objects.equals(item.getCart().getId(), cart.getId())) { + cartItemList.add(item); + } + } + } + return cartItemList; + } + + @Transactional + @Override + public void deleteCartItemsByOrder(Order order) { + List cartItems = order.getCartItems(); + cartItemRepository.deleteAllInBatch(cartItems); + } +} + diff --git a/src/main/java/project/trendpick_pro/domain/coupon/service/CouponService.java b/src/main/java/project/trendpick_pro/domain/coupon/service/CouponService.java index 5a47f012..abc334e4 100644 --- a/src/main/java/project/trendpick_pro/domain/coupon/service/CouponService.java +++ b/src/main/java/project/trendpick_pro/domain/coupon/service/CouponService.java @@ -1,7 +1,6 @@ package project.trendpick_pro.domain.coupon.service; import lombok.RequiredArgsConstructor; -import org.hibernate.annotations.Fetch; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import project.trendpick_pro.domain.coupon.entity.Coupon; From 4b67927e0b59eafa7eecc01a1ad663191c4a1fa7 Mon Sep 17 00:00:00 2001 From: jooooonj Date: Mon, 10 Jul 2023 17:26:33 +0900 Subject: [PATCH 08/26] =?UTF-8?q?refactor:=20Tag=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81(#353)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tags/favoritetag/entity/FavoriteTag.java | 3 +- .../service/FavoriteTagService.java | 47 ++----------------- .../service/FavoriteTagServiceImpl.java | 45 ++++++++++++++++++ .../entity/dto/response/TagListResponse.java | 16 ------- .../tag/entity/dto/response/TagResponse.java | 13 ----- .../domain/tags/tag/service/TagService.java | 28 +---------- .../tags/tag/service/TagServiceImpl.java | 26 ++++++++++ .../tags/{tag/entity => }/type/TagType.java | 2 +- 8 files changed, 79 insertions(+), 101 deletions(-) create mode 100644 src/main/java/project/trendpick_pro/domain/tags/favoritetag/service/FavoriteTagServiceImpl.java delete mode 100644 src/main/java/project/trendpick_pro/domain/tags/tag/entity/dto/response/TagListResponse.java delete mode 100644 src/main/java/project/trendpick_pro/domain/tags/tag/entity/dto/response/TagResponse.java create mode 100644 src/main/java/project/trendpick_pro/domain/tags/tag/service/TagServiceImpl.java rename src/main/java/project/trendpick_pro/domain/tags/{tag/entity => }/type/TagType.java (80%) diff --git a/src/main/java/project/trendpick_pro/domain/tags/favoritetag/entity/FavoriteTag.java b/src/main/java/project/trendpick_pro/domain/tags/favoritetag/entity/FavoriteTag.java index 32fc0ec8..4eff09c3 100644 --- a/src/main/java/project/trendpick_pro/domain/tags/favoritetag/entity/FavoriteTag.java +++ b/src/main/java/project/trendpick_pro/domain/tags/favoritetag/entity/FavoriteTag.java @@ -5,7 +5,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import project.trendpick_pro.domain.member.entity.Member; -import project.trendpick_pro.domain.tags.tag.entity.type.TagType; +import project.trendpick_pro.domain.tags.type.TagType; @Entity @Getter @@ -47,6 +47,7 @@ public void decreaseScore(TagType type){ switch (type) { case ORDER -> score -= 10; case CART -> score -= 5; + case REGISTER -> score -= 30; default -> score -= 1; } } diff --git a/src/main/java/project/trendpick_pro/domain/tags/favoritetag/service/FavoriteTagService.java b/src/main/java/project/trendpick_pro/domain/tags/favoritetag/service/FavoriteTagService.java index 935e308e..6bad910d 100644 --- a/src/main/java/project/trendpick_pro/domain/tags/favoritetag/service/FavoriteTagService.java +++ b/src/main/java/project/trendpick_pro/domain/tags/favoritetag/service/FavoriteTagService.java @@ -1,51 +1,10 @@ package project.trendpick_pro.domain.tags.favoritetag.service; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import project.trendpick_pro.domain.tags.favoritetag.entity.FavoriteTag; -import project.trendpick_pro.domain.tags.favoritetag.repository.FavoriteTagRepository; import project.trendpick_pro.domain.member.entity.Member; import project.trendpick_pro.domain.product.entity.product.Product; -import project.trendpick_pro.domain.tags.tag.entity.Tag; -import project.trendpick_pro.domain.tags.tag.entity.type.TagType; -import project.trendpick_pro.domain.tags.tag.repository.TagRepository; +import project.trendpick_pro.domain.tags.type.TagType; -import java.util.List; -import java.util.Set; +public interface FavoriteTagService { + void updateTag(Member member, Product product, TagType type); -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class FavoriteTagService { - private final FavoriteTagRepository favoriteTagRepository; - private final TagRepository tagRepository; - - public Set getAllTags(Member member) { - List list = favoriteTagRepository.findAll(); - return Set.copyOf(list); - } - - @Transactional - public void updateTag(Member member, Product product, TagType type) { - List tagList = tagRepository.findAllByProduct(product); - List tags = favoriteTagRepository.findAllByMember(member); - - for(Tag tagByProduct : tagList){ - boolean hasTag = false; - for(FavoriteTag tagByMember : tags){ - if(tagByProduct.getName().equals(tagByMember.getName())){ //기존에 가지고 있던 태그에는 점수 부여 - tagByMember.increaseScore(type); - hasTag = true; - break; - } - } - if(!hasTag){ //태그를 가지고 있지 않다면 추가해준다. - FavoriteTag favoriteTag = new FavoriteTag(tagByProduct.getName()); - favoriteTag.increaseScore(type); - member.addTag(favoriteTag); - favoriteTagRepository.save(favoriteTag); - } - } - } } diff --git a/src/main/java/project/trendpick_pro/domain/tags/favoritetag/service/FavoriteTagServiceImpl.java b/src/main/java/project/trendpick_pro/domain/tags/favoritetag/service/FavoriteTagServiceImpl.java new file mode 100644 index 00000000..d1eab617 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/tags/favoritetag/service/FavoriteTagServiceImpl.java @@ -0,0 +1,45 @@ +package project.trendpick_pro.domain.tags.favoritetag.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.tags.favoritetag.entity.FavoriteTag; +import project.trendpick_pro.domain.tags.favoritetag.repository.FavoriteTagRepository; +import project.trendpick_pro.domain.member.entity.Member; +import project.trendpick_pro.domain.product.entity.product.Product; +import project.trendpick_pro.domain.tags.tag.entity.Tag; +import project.trendpick_pro.domain.tags.type.TagType; +import project.trendpick_pro.domain.tags.tag.repository.TagRepository; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class FavoriteTagServiceImpl implements FavoriteTagService { + private final FavoriteTagRepository favoriteTagRepository; + private final TagRepository tagRepository; + + @Override + @Transactional + public void updateTag(Member member, Product product, TagType type) { + List tagList = tagRepository.findAllByProduct(product); + List tags = favoriteTagRepository.findAllByMember(member); + + for(Tag tagByProduct : tagList){ + boolean hasTag = false; + for(FavoriteTag tagByMember : tags){ + if(tagByProduct.getName().equals(tagByMember.getName())){ //기존에 가지고 있던 태그에는 점수 부여 + tagByMember.increaseScore(type); + hasTag = true; + break; + } + } + if(!hasTag){ //태그를 가지고 있지 않다면 추가해준다. + FavoriteTag favoriteTag = new FavoriteTag(tagByProduct.getName()); + favoriteTag.increaseScore(type); + member.addTag(favoriteTag); + favoriteTagRepository.save(favoriteTag); + } + } + } +} diff --git a/src/main/java/project/trendpick_pro/domain/tags/tag/entity/dto/response/TagListResponse.java b/src/main/java/project/trendpick_pro/domain/tags/tag/entity/dto/response/TagListResponse.java deleted file mode 100644 index e74274ff..00000000 --- a/src/main/java/project/trendpick_pro/domain/tags/tag/entity/dto/response/TagListResponse.java +++ /dev/null @@ -1,16 +0,0 @@ -package project.trendpick_pro.domain.tags.tag.entity.dto.response; - -import lombok.Getter; -import project.trendpick_pro.domain.tags.tag.entity.Tag; - -import java.util.List; - -@Getter -public class TagListResponse { - - private final List tags; - - public TagListResponse(List tags) { - this.tags = tags.stream().map(Tag::getName).toList(); - } -} \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/domain/tags/tag/entity/dto/response/TagResponse.java b/src/main/java/project/trendpick_pro/domain/tags/tag/entity/dto/response/TagResponse.java deleted file mode 100644 index e61ade17..00000000 --- a/src/main/java/project/trendpick_pro/domain/tags/tag/entity/dto/response/TagResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package project.trendpick_pro.domain.tags.tag.entity.dto.response; - -import lombok.Getter; - -@Getter -public class TagResponse { - - String tag; - - public TagResponse(String tag) { - this.tag = tag; - } -} diff --git a/src/main/java/project/trendpick_pro/domain/tags/tag/service/TagService.java b/src/main/java/project/trendpick_pro/domain/tags/tag/service/TagService.java index 6e703ee0..f8b9c665 100644 --- a/src/main/java/project/trendpick_pro/domain/tags/tag/service/TagService.java +++ b/src/main/java/project/trendpick_pro/domain/tags/tag/service/TagService.java @@ -1,33 +1,9 @@ package project.trendpick_pro.domain.tags.tag.service; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import project.trendpick_pro.domain.tags.tag.entity.Tag; -import project.trendpick_pro.domain.tags.tag.repository.TagRepository; -import java.util.List; import java.util.Set; -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class TagService { - - private final TagRepository tagRepository; - - public void save(String name) { - tagRepository.save(new Tag(name)); - } - - public List getAllTags() { - return tagRepository.findAll(); - } - - public void delete(Set tags) { - for (Tag tag : tags) { - tagRepository.delete(tag); - } - } - +public interface TagService { + void delete(Set tags); } diff --git a/src/main/java/project/trendpick_pro/domain/tags/tag/service/TagServiceImpl.java b/src/main/java/project/trendpick_pro/domain/tags/tag/service/TagServiceImpl.java new file mode 100644 index 00000000..157aa116 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/tags/tag/service/TagServiceImpl.java @@ -0,0 +1,26 @@ +package project.trendpick_pro.domain.tags.tag.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.tags.tag.entity.Tag; +import project.trendpick_pro.domain.tags.tag.repository.TagRepository; + +import java.util.List; +import java.util.Set; + +@Service +@RequiredArgsConstructor +public class TagServiceImpl implements TagService{ + + private final TagRepository tagRepository; + + @Override + @Transactional + public void delete(Set tags) { +// for (Tag tag : tags) { +// tagRepository.delete(tag); +// } + tagRepository.deleteAllInBatch(tags); + } +} diff --git a/src/main/java/project/trendpick_pro/domain/tags/tag/entity/type/TagType.java b/src/main/java/project/trendpick_pro/domain/tags/type/TagType.java similarity index 80% rename from src/main/java/project/trendpick_pro/domain/tags/tag/entity/type/TagType.java rename to src/main/java/project/trendpick_pro/domain/tags/type/TagType.java index 27cfaf0b..897bfc35 100644 --- a/src/main/java/project/trendpick_pro/domain/tags/tag/entity/type/TagType.java +++ b/src/main/java/project/trendpick_pro/domain/tags/type/TagType.java @@ -1,4 +1,4 @@ -package project.trendpick_pro.domain.tags.tag.entity.type; +package project.trendpick_pro.domain.tags.type; public enum TagType { //타입에 따라 다른 태그점수 향상치 ORDER("ORDER"), From 67d5e24255d097d2dbb2de6f3a557b9b763c7a2c Mon Sep 17 00:00:00 2001 From: jooooonj Date: Mon, 10 Jul 2023 17:27:48 +0900 Subject: [PATCH 09/26] =?UTF-8?q?refactor:=20Withdraw=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=EA=B5=AC=EC=A1=B0=20=EB=A6=AC=ED=8C=A9=ED=86=A0?= =?UTF-8?q?=EB=A7=81(#353)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/orders/service/OrderService.java | 2 +- .../controller/WithdrawController.java | 11 +- .../repository/WithdrawApplyRepository.java | 6 + .../withdraw/service/WithdrawService.java | 113 ++---------------- .../withdraw/service/WithdrawServiceImpl.java | 113 ++++++++++++++++++ .../controller/PaymentController.java | 2 - 6 files changed, 133 insertions(+), 114 deletions(-) create mode 100644 src/main/java/project/trendpick_pro/domain/withdraw/service/WithdrawServiceImpl.java diff --git a/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java b/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java index aa61fe70..571e156f 100644 --- a/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java +++ b/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java @@ -34,7 +34,7 @@ import project.trendpick_pro.domain.product.exception.ProductStockOutException; import project.trendpick_pro.domain.product.service.ProductService; import project.trendpick_pro.domain.tags.favoritetag.service.FavoriteTagService; -import project.trendpick_pro.domain.tags.tag.entity.type.TagType; +import project.trendpick_pro.domain.tags.type.TagType; import project.trendpick_pro.global.rsData.RsData; import java.util.ArrayList; diff --git a/src/main/java/project/trendpick_pro/domain/withdraw/controller/WithdrawController.java b/src/main/java/project/trendpick_pro/domain/withdraw/controller/WithdrawController.java index fb93280a..bbc1c84c 100644 --- a/src/main/java/project/trendpick_pro/domain/withdraw/controller/WithdrawController.java +++ b/src/main/java/project/trendpick_pro/domain/withdraw/controller/WithdrawController.java @@ -26,18 +26,19 @@ public class WithdrawController { private final MemberService memberService; private final Rq rq; + + @PreAuthorize("hasAuthority({'BRAND_ADMIN'})") @GetMapping("/withDraw") public String showApply(Model model) { - if(!rq.getRollMember().getRole().getValue().equals("BRAND_ADMIN")){ + Member member = rq.getRollMember(); + if(!member.getRole().getValue().equals("BRAND_ADMIN")){ return rq.historyBack("브랜드 관리자만 접근할 수 있습니다."); } - long actorRestCash = memberService.getRestCash(rq.getBrandMember()); - model.addAttribute("actorRestCash", actorRestCash); - + model.addAttribute("actorRestCash", memberService.getRestCash(member)); return "trendpick/admin/withDraw"; } - @PreAuthorize("isAuthenticated()") + @PreAuthorize("hasAuthority({'BRAND_ADMIN'})") @PostMapping("/withDraw") public String apply(@Valid WithDrawApplyForm withDrawApplyForm) { RsData rsData = withdrawService.apply( diff --git a/src/main/java/project/trendpick_pro/domain/withdraw/repository/WithdrawApplyRepository.java b/src/main/java/project/trendpick_pro/domain/withdraw/repository/WithdrawApplyRepository.java index e6768f93..b4d1f9bb 100644 --- a/src/main/java/project/trendpick_pro/domain/withdraw/repository/WithdrawApplyRepository.java +++ b/src/main/java/project/trendpick_pro/domain/withdraw/repository/WithdrawApplyRepository.java @@ -1,8 +1,14 @@ package project.trendpick_pro.domain.withdraw.repository; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import project.trendpick_pro.domain.withdraw.entity.WithdrawApply; +import java.util.List; + public interface WithdrawApplyRepository extends JpaRepository { + @Query("select w from WithdrawApply w where w.applicant.id = :id") + List findAllByApplicantId(@Param("id") Long id); } diff --git a/src/main/java/project/trendpick_pro/domain/withdraw/service/WithdrawService.java b/src/main/java/project/trendpick_pro/domain/withdraw/service/WithdrawService.java index f10bd424..98423433 100644 --- a/src/main/java/project/trendpick_pro/domain/withdraw/service/WithdrawService.java +++ b/src/main/java/project/trendpick_pro/domain/withdraw/service/WithdrawService.java @@ -1,114 +1,15 @@ package project.trendpick_pro.domain.withdraw.service; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import project.trendpick_pro.domain.brand.entity.Brand; -import project.trendpick_pro.domain.brand.service.BrandService; -import project.trendpick_pro.domain.cash.entity.CashLog; import project.trendpick_pro.domain.member.entity.Member; -import project.trendpick_pro.domain.member.service.MemberService; import project.trendpick_pro.domain.withdraw.entity.WithdrawApply; -import project.trendpick_pro.domain.withdraw.repository.WithdrawApplyRepository; import project.trendpick_pro.global.rsData.RsData; -import project.trendpick_pro.global.util.Ut; -import java.util.ArrayList; import java.util.List; -import java.util.Objects; -@Service -@Slf4j -@RequiredArgsConstructor -@Transactional -public class WithdrawService { - private final WithdrawApplyRepository withdrawApplyRepository; - private final MemberService memberService; - private final BrandService brandService; - public RsData apply(String bankName, String bankAccountNo, Integer price, Member applicant) { - WithdrawApply withdrawApply = WithdrawApply.builder() - .bankName(bankName) - .bankAccountNo(bankAccountNo) - .price(price) - .applicant(applicant) - .build(); - - withdrawApplyRepository.save(withdrawApply); - - return RsData.of("S-1", "출금 신청이 완료되었습니다.", withdrawApply); - } - - public List findAll() { - return withdrawApplyRepository.findAll(); - } - - public List findByWithdrawApplyId(Long id){ - List findByWithdrawApplyList=withdrawApplyRepository.findAll(); - List withdrawApplyList=new ArrayList<>(); - - for(WithdrawApply withdrawApply: findByWithdrawApplyList){ - if(Objects.equals(withdrawApply.getApplicant().getId(),id)){ - withdrawApplyList.add(withdrawApply); - } - } - return withdrawApplyList; - } - - public RsData withdraw(Long withdrawApplyId) { - WithdrawApply withdrawApply = withdrawApplyRepository.findById(withdrawApplyId).orElse(null); - - if (withdrawApply == null) { - return RsData.of("F-1", "출금신청 데이터를 찾을 수 없습니다."); - } - - if (withdrawApply.isApplyDoneAvailable() == false) { - return RsData.of("F-2", "이미 처리되었습니다."); - } - - long restCash = memberService.getRestCash(withdrawApply.getApplicant()); - - if (withdrawApply.getPrice() > restCash) { - return RsData.of("F-3", "예치금이 부족합니다."); - } - Brand brand=brandService.findByName(withdrawApply.getApplicant().getBrand()); - - CashLog cashLog = memberService.addCash( - withdrawApply.getApplicant().getBrand(), - withdrawApply.getPrice() * -1, - brand, - CashLog.EvenType.출금__통장입금 - ) - .getData().getCashLog(); - - withdrawApply.setApplyDone(cashLog.getId(), "관리자에 의해서 처리되었습니다."); - - return RsData.of( - "S-1", - "%d번 출금신청이 처리되었습니다. %s원이 출금되었습니다.".formatted(withdrawApply.getId(), Ut.nf(withdrawApply.getPrice())), - Ut.mapOf( - "cashLogId", cashLog.getId() - ) - ); - } - - public RsData cancelApply(Long withdrawApplyId) { - WithdrawApply withdrawApply = withdrawApplyRepository.findById(withdrawApplyId).orElse(null); - - if (withdrawApply == null) { - return RsData.of("F-1", "출금신청 데이터를 찾을 수 없습니다."); - } - - if (withdrawApply.isCancelAvailable() == false) { - return RsData.of("F-2", "취소가 불가능합니다."); - } - - withdrawApply.setCancelDone("관리자에 의해서 취소되었습니다."); - - return RsData.of( - "S-1", - "%d번 출금신청이 취소되었습니다.".formatted(withdrawApply.getId()), - null - ); - } -} \ No newline at end of file +public interface WithdrawService { + RsData apply(String bankName, String bankAccountNo, Integer price, Member applicant); + List findAll(); + List findByWithdrawApplyId(Long id); + RsData withdraw(Long withdrawApplyId); + RsData cancelApply(Long withdrawApplyId); +} diff --git a/src/main/java/project/trendpick_pro/domain/withdraw/service/WithdrawServiceImpl.java b/src/main/java/project/trendpick_pro/domain/withdraw/service/WithdrawServiceImpl.java new file mode 100644 index 00000000..6f45e1ad --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/withdraw/service/WithdrawServiceImpl.java @@ -0,0 +1,113 @@ +package project.trendpick_pro.domain.withdraw.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.brand.entity.Brand; +import project.trendpick_pro.domain.brand.service.BrandService; +import project.trendpick_pro.domain.cash.entity.CashLog; +import project.trendpick_pro.domain.member.entity.Member; +import project.trendpick_pro.domain.member.service.MemberService; +import project.trendpick_pro.domain.withdraw.entity.WithdrawApply; +import project.trendpick_pro.domain.withdraw.repository.WithdrawApplyRepository; +import project.trendpick_pro.global.rsData.RsData; +import project.trendpick_pro.global.util.Ut; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +@Service +@Slf4j +@RequiredArgsConstructor +public class WithdrawServiceImpl implements WithdrawService{ + private final WithdrawApplyRepository withdrawApplyRepository; + private final MemberService memberService; + private final BrandService brandService; + @Transactional + @Override + public RsData apply(String bankName, String bankAccountNo, Integer price, Member applicant) { + WithdrawApply withdrawApply = WithdrawApply.builder() + .bankName(bankName) + .bankAccountNo(bankAccountNo) + .price(price) + .applicant(applicant) + .build(); + + withdrawApplyRepository.save(withdrawApply); + + return RsData.of("S-1", "출금 신청이 완료되었습니다.", withdrawApply); + } + + @Transactional(readOnly = true) + @Override + public List findAll() { + return withdrawApplyRepository.findAll(); + } + + @Transactional(readOnly = true) + @Override + public List findByWithdrawApplyId(Long id){ + return withdrawApplyRepository.findAllByApplicantId(id); + } + + @Transactional + public RsData withdraw(Long withdrawApplyId) { + WithdrawApply withdrawApply = withdrawApplyRepository.findById(withdrawApplyId).orElse(null); + + if (withdrawApply == null) { + return RsData.of("F-1", "출금신청 데이터를 찾을 수 없습니다."); + } + + if (withdrawApply.isApplyDoneAvailable() == false) { + return RsData.of("F-2", "이미 처리되었습니다."); + } + + long restCash = memberService.getRestCash(withdrawApply.getApplicant()); + + if (withdrawApply.getPrice() > restCash) { + return RsData.of("F-3", "예치금이 부족합니다."); + } + Brand brand=brandService.findByName(withdrawApply.getApplicant().getBrand()); + + CashLog cashLog = memberService.addCash( + withdrawApply.getApplicant().getBrand(), + withdrawApply.getPrice() * -1, + brand, + CashLog.EvenType.출금__통장입금 + ) + .getData().getCashLog(); + + withdrawApply.setApplyDone(cashLog.getId(), "관리자에 의해서 처리되었습니다."); + + return RsData.of( + "S-1", + "%d번 출금신청이 처리되었습니다. %s원이 출금되었습니다.".formatted(withdrawApply.getId(), Ut.nf(withdrawApply.getPrice())), + Ut.mapOf( + "cashLogId", cashLog.getId() + ) + ); + } + + @Transactional + public RsData cancelApply(Long withdrawApplyId) { + WithdrawApply withdrawApply = withdrawApplyRepository.findById(withdrawApplyId).orElse(null); + + if (withdrawApply == null) { + return RsData.of("F-1", "출금신청 데이터를 찾을 수 없습니다."); + } + + if (withdrawApply.isCancelAvailable() == false) { + return RsData.of("F-2", "취소가 불가능합니다."); + } + + withdrawApply.setCancelDone("관리자에 의해서 취소되었습니다."); + + return RsData.of( + "S-1", + "%d번 출금신청이 취소되었습니다.".formatted(withdrawApply.getId()), + null + ); + } +} \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/global/tosspayment/controller/PaymentController.java b/src/main/java/project/trendpick_pro/global/tosspayment/controller/PaymentController.java index 33e4aee9..d9042cd9 100644 --- a/src/main/java/project/trendpick_pro/global/tosspayment/controller/PaymentController.java +++ b/src/main/java/project/trendpick_pro/global/tosspayment/controller/PaymentController.java @@ -4,7 +4,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; -import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -14,7 +13,6 @@ import project.trendpick_pro.domain.member.entity.Member; import project.trendpick_pro.domain.notification.service.NotificationService; import project.trendpick_pro.domain.orders.entity.Order; -import project.trendpick_pro.domain.orders.entity.OrderStatus; import project.trendpick_pro.domain.orders.service.OrderService; import project.trendpick_pro.global.rsData.RsData; import project.trendpick_pro.global.tosspayment.dto.PaymentResultResponse; From c5f776bb2fa1c5b122e9e89fcb8f5e2b2562eb95 Mon Sep 17 00:00:00 2001 From: jooooonj Date: Mon, 10 Jul 2023 17:28:46 +0900 Subject: [PATCH 10/26] =?UTF-8?q?refactor:=20Store=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81=20(#353)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/common/base/rq/Rq.java | 10 +------ .../domain/member/entity/Member.java | 3 +- .../domain/store/entity/Store.java | 3 -- .../store/repository/StoreRepository.java | 2 -- .../domain/store/service/StoreService.java | 29 ++----------------- .../store/service/StoreServiceImpl.java | 27 +++++++++++++++++ ...Controller.java => JobTestController.java} | 21 +++++--------- 7 files changed, 40 insertions(+), 55 deletions(-) create mode 100644 src/main/java/project/trendpick_pro/domain/store/service/StoreServiceImpl.java rename src/main/java/project/trendpick_pro/global/job/{JobController.java => JobTestController.java} (69%) diff --git a/src/main/java/project/trendpick_pro/domain/common/base/rq/Rq.java b/src/main/java/project/trendpick_pro/domain/common/base/rq/Rq.java index 2fe400c5..fda360fb 100644 --- a/src/main/java/project/trendpick_pro/domain/common/base/rq/Rq.java +++ b/src/main/java/project/trendpick_pro/domain/common/base/rq/Rq.java @@ -158,15 +158,7 @@ public Member getMember() { } public Member getRollMember(){ - Member member=getLogin(); - if(member.getRole().equals(RoleType.MEMBER)){ - return member; - }else if(member.getRole().equals(RoleType.BRAND_ADMIN)){ - return member; - }else if(member.getRole().equals(RoleType.ADMIN)){ - return member; - } - throw new MemberNotMatchException("허용된 권한이 아닙니다."); + return getLogin(); } public Member getBrandMember() { Member member = getLogin(); diff --git a/src/main/java/project/trendpick_pro/domain/member/entity/Member.java b/src/main/java/project/trendpick_pro/domain/member/entity/Member.java index 8e973a6d..82ddb635 100644 --- a/src/main/java/project/trendpick_pro/domain/member/entity/Member.java +++ b/src/main/java/project/trendpick_pro/domain/member/entity/Member.java @@ -2,12 +2,11 @@ import jakarta.persistence.*; import lombok.*; -import project.trendpick_pro.domain.brand.entity.Brand; import project.trendpick_pro.domain.cart.entity.Cart; import project.trendpick_pro.domain.common.base.BaseTimeEntity; import project.trendpick_pro.domain.orders.entity.Order; import project.trendpick_pro.domain.tags.favoritetag.entity.FavoriteTag; -import project.trendpick_pro.domain.tags.tag.entity.type.TagType; +import project.trendpick_pro.domain.tags.type.TagType; import java.time.LocalDateTime; import java.util.ArrayList; diff --git a/src/main/java/project/trendpick_pro/domain/store/entity/Store.java b/src/main/java/project/trendpick_pro/domain/store/entity/Store.java index efc76ad2..78e75b71 100644 --- a/src/main/java/project/trendpick_pro/domain/store/entity/Store.java +++ b/src/main/java/project/trendpick_pro/domain/store/entity/Store.java @@ -2,7 +2,6 @@ import jakarta.persistence.*; import lombok.AccessLevel; -import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import project.trendpick_pro.domain.common.base.BaseTimeEntity; @@ -16,8 +15,6 @@ public class Store extends BaseTimeEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - // @OneToOne(fetch = FetchType.LAZY) -// @JoinColumn(name = "brand") @Column(unique = true) private String brand; //임시 diff --git a/src/main/java/project/trendpick_pro/domain/store/repository/StoreRepository.java b/src/main/java/project/trendpick_pro/domain/store/repository/StoreRepository.java index 5c5bf15f..57da303c 100644 --- a/src/main/java/project/trendpick_pro/domain/store/repository/StoreRepository.java +++ b/src/main/java/project/trendpick_pro/domain/store/repository/StoreRepository.java @@ -2,9 +2,7 @@ import org.springframework.data.jpa.repository.JpaRepository; import project.trendpick_pro.domain.store.entity.Store; - import java.util.Optional; - public interface StoreRepository extends JpaRepository { Optional findByBrand(String brand); } diff --git a/src/main/java/project/trendpick_pro/domain/store/service/StoreService.java b/src/main/java/project/trendpick_pro/domain/store/service/StoreService.java index 36ba38d1..f0593249 100644 --- a/src/main/java/project/trendpick_pro/domain/store/service/StoreService.java +++ b/src/main/java/project/trendpick_pro/domain/store/service/StoreService.java @@ -1,31 +1,8 @@ package project.trendpick_pro.domain.store.service; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import project.trendpick_pro.domain.store.entity.Store; -import project.trendpick_pro.domain.store.repository.StoreRepository; -@Service -@Transactional(readOnly = true) -@RequiredArgsConstructor -public class StoreService { - private final StoreRepository storeRepository; - - @Transactional - public Store save(Store store){ - return storeRepository.save(store); - } - - public Store findById(Long storeId) { - return storeRepository.findById(storeId).orElseThrow( - () -> new IllegalArgumentException("해당 스토어는 존재하지 않는 스토어입니다.") - ); - } - - public Store findByBrand(String storeName) { - return storeRepository.findByBrand(storeName).orElseThrow( - () -> new IllegalArgumentException("해당 스토어는 존재하지 않는 스토어입니다.") - ); - } +public interface StoreService { + Store save(Store store); + Store findByBrand(String storeName); } diff --git a/src/main/java/project/trendpick_pro/domain/store/service/StoreServiceImpl.java b/src/main/java/project/trendpick_pro/domain/store/service/StoreServiceImpl.java new file mode 100644 index 00000000..2fedaba3 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/store/service/StoreServiceImpl.java @@ -0,0 +1,27 @@ +package project.trendpick_pro.domain.store.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.store.entity.Store; +import project.trendpick_pro.domain.store.repository.StoreRepository; + +@Service +@RequiredArgsConstructor +public class StoreServiceImpl implements StoreService{ + private final StoreRepository storeRepository; + + @Override + @Transactional + public Store save(Store store){ + return storeRepository.save(store); + } + + @Override + @Transactional(readOnly = true) + public Store findByBrand(String storeName) { + return storeRepository.findByBrand(storeName).orElseThrow( + () -> new IllegalArgumentException("해당 스토어는 존재하지 않는 스토어입니다.") + ); + } +} diff --git a/src/main/java/project/trendpick_pro/global/job/JobController.java b/src/main/java/project/trendpick_pro/global/job/JobTestController.java similarity index 69% rename from src/main/java/project/trendpick_pro/global/job/JobController.java rename to src/main/java/project/trendpick_pro/global/job/JobTestController.java index 69a5914f..9f446c69 100644 --- a/src/main/java/project/trendpick_pro/global/job/JobController.java +++ b/src/main/java/project/trendpick_pro/global/job/JobTestController.java @@ -1,24 +1,19 @@ package project.trendpick_pro.global.job; -import jdk.jfr.Category; -import lombok.Getter; import lombok.RequiredArgsConstructor; import org.springframework.batch.core.JobParametersInvalidException; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; import org.springframework.batch.core.repository.JobRestartException; import org.springframework.stereotype.Controller; -import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; -import project.trendpick_pro.global.job.JobConfig; @Controller @RequiredArgsConstructor @RequestMapping("/job") -public class JobController { +public class JobTestController { private final JobConfig jobConfig; @@ -28,9 +23,9 @@ public String test(){ try { jobConfig.performMakeRecommendProductJob(); } catch (Exception e) { - throw new RuntimeException("Job 실행 실패"); + throw new RuntimeException("추천 잡실행 실패"); } - return "잡실행 성공"; + return "추천 잡실행 성공"; } @GetMapping("/order") @@ -39,14 +34,14 @@ public String cancelOrderJob(){ try { jobConfig.performCancelOrderJob(); } catch (JobInstanceAlreadyCompleteException e) { - throw new RuntimeException(e); + throw new RuntimeException("주문삭제 잡실패"); } catch (JobExecutionAlreadyRunningException e) { - throw new RuntimeException(e); + throw new RuntimeException("주문삭제 잡실패"); } catch (JobParametersInvalidException e) { - throw new RuntimeException(e); + throw new RuntimeException("주문삭제 잡실패"); } catch (JobRestartException e) { - throw new RuntimeException(e); + throw new RuntimeException("주문삭제 잡실패"); } - return "성공"; + return "주문삭제 잡성공"; } } From 28d488a2d0b9a573c68271140ad54e9c8ea60abe Mon Sep 17 00:00:00 2001 From: jooooonj Date: Mon, 10 Jul 2023 17:43:08 +0900 Subject: [PATCH 11/26] =?UTF-8?q?fix:=20=EC=BB=B4=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95=20(#353)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trendpick_pro/domain/product/service/ProductService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/project/trendpick_pro/domain/product/service/ProductService.java b/src/main/java/project/trendpick_pro/domain/product/service/ProductService.java index c7260e44..0ec76826 100644 --- a/src/main/java/project/trendpick_pro/domain/product/service/ProductService.java +++ b/src/main/java/project/trendpick_pro/domain/product/service/ProductService.java @@ -37,8 +37,8 @@ import project.trendpick_pro.domain.tags.favoritetag.entity.FavoriteTag; import project.trendpick_pro.domain.tags.favoritetag.service.FavoriteTagService; import project.trendpick_pro.domain.tags.tag.entity.Tag; -import project.trendpick_pro.domain.tags.tag.entity.type.TagType; import project.trendpick_pro.domain.tags.tag.service.TagService; +import project.trendpick_pro.domain.tags.type.TagType; import project.trendpick_pro.global.rsData.RsData; //import project.trendpick_pro.global.search.service.SearchService; @@ -170,7 +170,7 @@ public ProductResponse getProduct(Long productId) { } @Transactional(readOnly = true) - private ProductListResponse getProducts(Long productId) { + public ProductListResponse getProducts(Long productId) { Product product = productRepository.findById(productId).orElseThrow(() -> new ProductNotFoundException("존재하지 않는 상품입니다.")); return ProductListResponse.of(product); } From 8ef9fde4d6c83861effcc0d635b01ab3d4fdc1d8 Mon Sep 17 00:00:00 2001 From: mmunkyeong Date: Mon, 10 Jul 2023 17:58:25 +0900 Subject: [PATCH 12/26] =?UTF-8?q?refactor:=20Rebate=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81(#354)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/rebate/service/RebateService.java | 109 +--------------- .../rebate/service/RebateServiceImpl.java | 116 ++++++++++++++++++ 2 files changed, 122 insertions(+), 103 deletions(-) create mode 100644 src/main/java/project/trendpick_pro/domain/rebate/service/RebateServiceImpl.java diff --git a/src/main/java/project/trendpick_pro/domain/rebate/service/RebateService.java b/src/main/java/project/trendpick_pro/domain/rebate/service/RebateService.java index 32c52e35..cf6a18c5 100644 --- a/src/main/java/project/trendpick_pro/domain/rebate/service/RebateService.java +++ b/src/main/java/project/trendpick_pro/domain/rebate/service/RebateService.java @@ -1,116 +1,19 @@ package project.trendpick_pro.domain.rebate.service; -import org.springframework.transaction.annotation.Transactional; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import project.trendpick_pro.domain.cash.entity.CashLog; -import project.trendpick_pro.domain.member.service.MemberService; import project.trendpick_pro.domain.orders.entity.OrderItem; -import project.trendpick_pro.domain.orders.service.OrderService; import project.trendpick_pro.domain.rebate.entity.RebateOrderItem; -import project.trendpick_pro.domain.rebate.repository.RebateOrderItemRepository; import project.trendpick_pro.global.rsData.RsData; -import project.trendpick_pro.global.util.Ut; -import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.List; -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class RebateService { - private final OrderService orderService; - private final MemberService memberService; - private final RebateOrderItemRepository rebateOrderItemRepository; - @Transactional - public RsData makeDate(String brandName,String yearMonth) { - int monthEndDay = Ut.date.getEndDayOf(yearMonth); +public interface RebateService { + RsData makeDate(String brandName,String yearMonth); - String fromDateStr = yearMonth + "-01 00:00:00.000000"; - String toDateStr = yearMonth + "-%02d 23:59:59.999999".formatted(monthEndDay); - LocalDateTime fromDate = Ut.date.parse(fromDateStr); - LocalDateTime toDate = Ut.date.parse(toDateStr); + void makeRebateOrderItem(RebateOrderItem item); - // 데이터 가져오기 - List orderItems = orderService.findAllByPayDateBetweenOrderByIdAsc(fromDate, toDate); + RebateOrderItem toRebateOrderItem(OrderItem orderItem); - if(orderItems.isEmpty()){ - return RsData.of("F-1","정산할 주문내역이 없습니다."); - } - List brandOrderItems=new ArrayList<>(); - for(OrderItem item: orderItems) { - if (item.getProduct().getBrand().getName().equals(brandName)) { - brandOrderItems.add(item); - } - } - - // 변환하기 - List rebateOrderItems = brandOrderItems - .stream() - .map(this::toRebateOrderItem) - .toList(); - - // 저장하기 - rebateOrderItems.forEach(item -> makeRebateOrderItem(brandName,item)); - return RsData.of("S-1", "정산데이터가 성공적으로 생성되었습니다."); - } - - @Transactional - public void makeRebateOrderItem(String brandName,RebateOrderItem item) { - RebateOrderItem oldRebateOrderItem = rebateOrderItemRepository.findByOrderItemId(item.getOrderItem().getId()).orElse(null); - - if (oldRebateOrderItem != null) { - if (oldRebateOrderItem.isRebateDone()) { - return; - } - - oldRebateOrderItem.updateWith(item); - - rebateOrderItemRepository.save(oldRebateOrderItem); - } else { - rebateOrderItemRepository.save(item); - } - } - - public RebateOrderItem toRebateOrderItem(OrderItem orderItem) { - return new RebateOrderItem(orderItem); - } - - public List findRebateOrderItemsByPayDateIn(String brandName,String yearMonth) { - int monthEndDay = Ut.date.getEndDayOf(yearMonth); - - String fromDateStr = yearMonth + "-01 00:00:00.000000"; - String toDateStr = yearMonth + "-%02d 23:59:59.999999".formatted(monthEndDay); - LocalDateTime fromDate = Ut.date.parse(fromDateStr); - LocalDateTime toDate = Ut.date.parse(toDateStr); - - return rebateOrderItemRepository.findAllByPayDateBetweenAndSellerNameOrderByIdAsc(fromDate, toDate,brandName); - } - - @Transactional - public RsData rebate(long orderItemId) { - RebateOrderItem rebateOrderItem = rebateOrderItemRepository.findByOrderItemId(orderItemId).get(); - - if (rebateOrderItem.isRebateAvailable() == false) { - return RsData.of("F-1", "정산을 할 수 없는 상태입니다."); - } - - int calculateRebatePrice = rebateOrderItem.calculateRebatePrice(); - - CashLog cashLog = memberService.addCash( - rebateOrderItem.getSellerName(), - calculateRebatePrice, - rebateOrderItem.getSeller(), - CashLog.EvenType.브랜드정산__예치금 - ).getData().getCashLog(); - - - rebateOrderItem.setRebateDone(cashLog.getId()); - return RsData.of( - "S-1", - "주문품목번호 %d번에 대해서 정산을 완료하였습니다.".formatted(rebateOrderItem.getOrderItem().getId()) - ); - } + List findRebateOrderItemsByPayDateIn(String brandName,String yearMonth); + RsData rebate(long orderItemId); } \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/domain/rebate/service/RebateServiceImpl.java b/src/main/java/project/trendpick_pro/domain/rebate/service/RebateServiceImpl.java new file mode 100644 index 00000000..e1a1ea70 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/rebate/service/RebateServiceImpl.java @@ -0,0 +1,116 @@ +package project.trendpick_pro.domain.rebate.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.cash.entity.CashLog; +import project.trendpick_pro.domain.member.service.MemberService; +import project.trendpick_pro.domain.orders.entity.OrderItem; +import project.trendpick_pro.domain.orders.service.OrderService; +import project.trendpick_pro.domain.rebate.entity.RebateOrderItem; +import project.trendpick_pro.domain.rebate.repository.RebateOrderItemRepository; +import project.trendpick_pro.global.rsData.RsData; +import project.trendpick_pro.global.util.Ut; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@Service +@RequiredArgsConstructor +public class RebateServiceImpl implements RebateService{ + private final OrderService orderService; + private final MemberService memberService; + private final RebateOrderItemRepository rebateOrderItemRepository; + + @Transactional + public RsData makeDate(String brandName, String yearMonth) { + int monthEndDay = Ut.date.getEndDayOf(yearMonth); + + String fromDateStr = yearMonth + "-01 00:00:00.000000"; + String toDateStr = yearMonth + "-%02d 23:59:59.999999".formatted(monthEndDay); + LocalDateTime fromDate = Ut.date.parse(fromDateStr); + LocalDateTime toDate = Ut.date.parse(toDateStr); + + // 데이터 가져오기 + List orderItems = orderService.findAllByPayDateBetweenOrderByIdAsc(fromDate, toDate); + + if(orderItems.isEmpty()){ + return RsData.of("F-1","정산할 주문내역이 없습니다."); + } + List brandOrderItems=new ArrayList<>(); + for(OrderItem item: orderItems) { + if (item.getProduct().getBrand().getName().equals(brandName)) { + brandOrderItems.add(item); + } + } + + // 변환하기 + List rebateOrderItems = brandOrderItems + .stream() + .map(this::toRebateOrderItem) + .toList(); + + // 저장하기 + rebateOrderItems.forEach(item -> makeRebateOrderItem(item)); + return RsData.of("S-1", "정산데이터가 성공적으로 생성되었습니다."); + } + + @Transactional + public void makeRebateOrderItem(RebateOrderItem item) { + RebateOrderItem oldRebateOrderItem = rebateOrderItemRepository.findByOrderItemId(item.getOrderItem().getId()).orElse(null); + + if (oldRebateOrderItem != null) { + if (oldRebateOrderItem.isRebateDone()) { + return; + } + + oldRebateOrderItem.updateWith(item); + + rebateOrderItemRepository.save(oldRebateOrderItem); + } else { + rebateOrderItemRepository.save(item); + } + } + @Transactional + public RebateOrderItem toRebateOrderItem(OrderItem orderItem) { + return new RebateOrderItem(orderItem); + } + + @Transactional(readOnly = true) + public List findRebateOrderItemsByPayDateIn(String brandName,String yearMonth) { + int monthEndDay = Ut.date.getEndDayOf(yearMonth); + + String fromDateStr = yearMonth + "-01 00:00:00.000000"; + String toDateStr = yearMonth + "-%02d 23:59:59.999999".formatted(monthEndDay); + LocalDateTime fromDate = Ut.date.parse(fromDateStr); + LocalDateTime toDate = Ut.date.parse(toDateStr); + + return rebateOrderItemRepository.findAllByPayDateBetweenAndSellerNameOrderByIdAsc(fromDate, toDate,brandName); + } + + @Transactional + public RsData rebate(long orderItemId) { + RebateOrderItem rebateOrderItem = rebateOrderItemRepository.findByOrderItemId(orderItemId).get(); + + if (rebateOrderItem.isRebateAvailable() == false) { + return RsData.of("F-1", "정산을 할 수 없는 상태입니다."); + } + + int calculateRebatePrice = rebateOrderItem.calculateRebatePrice(); + + CashLog cashLog = memberService.addCash( + rebateOrderItem.getSellerName(), + calculateRebatePrice, + rebateOrderItem.getSeller(), + CashLog.EvenType.브랜드정산__예치금 + ).getData().getCashLog(); + + + rebateOrderItem.setRebateDone(cashLog.getId()); + return RsData.of( + "S-1", + "주문품목번호 %d번에 대해서 정산을 완료하였습니다.".formatted(rebateOrderItem.getOrderItem().getId()) + ); + } +} \ No newline at end of file From 5acf26dd7a0787b18346dc0e00069690d12d7bd0 Mon Sep 17 00:00:00 2001 From: hye-0000 Date: Mon, 10 Jul 2023 18:23:03 +0900 Subject: [PATCH 13/26] =?UTF-8?q?refactor:=20=EA=B2=B0=EC=A0=9C=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/orders/service/OrderService.java | 2 +- .../tosspayment/service/PaymentService.java | 61 +++++++++++++++++- .../service/PaymentServiceImpl.java | 63 ------------------- 3 files changed, 59 insertions(+), 67 deletions(-) delete mode 100644 src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentServiceImpl.java diff --git a/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java b/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java index 571e156f..170737fb 100644 --- a/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java +++ b/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java @@ -115,7 +115,7 @@ public RsData productToOrder(Member member, Long id, int quantity, String @KafkaListener(topicPattern = "orders", groupId = "group_id") public void orderToOrder(@Payload String Id) throws JsonProcessingException { try { - Thread.sleep(750); + Thread.sleep(800); } catch (InterruptedException e) { e.printStackTrace(); } diff --git a/src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentService.java b/src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentService.java index 991a905f..b59dcf9f 100644 --- a/src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentService.java +++ b/src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentService.java @@ -1,8 +1,63 @@ package project.trendpick_pro.global.tosspayment.service; +import net.minidev.json.JSONObject; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; import project.trendpick_pro.global.tosspayment.dto.PaymentResultResponse; -public interface PaymentService { - PaymentResultResponse requestPayment(String paymentKey, String orderId, Integer amount); - void cancelPayment(String paymentKey); +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.Base64; +import java.util.Collections; + +@Service +public class PaymentService { + + @Value("${toss.secretKey}") + private String secretKey; + + @Value("${toss.url}") + private String tossURL; + + public PaymentResultResponse requestPayment(String paymentKey, String orderId, Integer amount) { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + String secret = new String(Base64.getEncoder().encode((secretKey + ":").getBytes(StandardCharsets.UTF_8))); + + headers.setBasicAuth(secret); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + + JSONObject params = new JSONObject(); + params.put("orderId", orderId); + params.put("amount", String.valueOf(amount)); + + return restTemplate.postForEntity(tossURL + paymentKey, new HttpEntity<>(params, headers), PaymentResultResponse.class).getBody(); + } + + public void cancelPayment(String paymentKey) { + + URI uri = URI.create(tossURL + paymentKey + "/cancel"); + + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + String secret = new String(Base64.getEncoder().encode((secretKey + ":").getBytes(StandardCharsets.UTF_8))); + + headers.setBasicAuth(secret); + headers.setContentType(MediaType.APPLICATION_JSON); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + + JSONObject params = new JSONObject(); + params.put("cancelReason", "단순 변심"); + + restTemplate.postForObject( + uri, + new HttpEntity<>(params, headers), + PaymentResultResponse.class + ); + } } \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentServiceImpl.java b/src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentServiceImpl.java deleted file mode 100644 index 53fd2b0b..00000000 --- a/src/main/java/project/trendpick_pro/global/tosspayment/service/PaymentServiceImpl.java +++ /dev/null @@ -1,63 +0,0 @@ -package project.trendpick_pro.global.tosspayment.service; - -import net.minidev.json.JSONObject; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; -import project.trendpick_pro.global.tosspayment.dto.PaymentResultResponse; - -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.Collections; - -@Service -public class PaymentServiceImpl implements PaymentService{ - - @Value("${toss.secretKey}") - private String secretKey; - - @Value("${toss.url}") - private String tossURL; - - public PaymentResultResponse requestPayment(String paymentKey, String orderId, Integer amount) { - RestTemplate restTemplate = new RestTemplate(); - HttpHeaders headers = new HttpHeaders(); - String secret = new String(Base64.getEncoder().encode((secretKey + ":").getBytes(StandardCharsets.UTF_8))); - - headers.setBasicAuth(secret); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); - - JSONObject params = new JSONObject(); - params.put("orderId", orderId); - params.put("amount", String.valueOf(amount)); - - return restTemplate.postForEntity(tossURL + paymentKey, new HttpEntity<>(params, headers), PaymentResultResponse.class).getBody(); - } - - public void cancelPayment(String paymentKey) { - - URI uri = URI.create(tossURL + paymentKey + "/cancel"); - - RestTemplate restTemplate = new RestTemplate(); - HttpHeaders headers = new HttpHeaders(); - String secret = new String(Base64.getEncoder().encode((secretKey + ":").getBytes(StandardCharsets.UTF_8))); - - headers.setBasicAuth(secret); - headers.setContentType(MediaType.APPLICATION_JSON); - headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); - - JSONObject params = new JSONObject(); - params.put("cancelReason", "단순 변심"); - - restTemplate.postForObject( - uri, - new HttpEntity<>(params, headers), - PaymentResultResponse.class - ); - } -} From f75ebaaab9a4d8d89f9cb93e3451a73440793c6d Mon Sep 17 00:00:00 2001 From: mmunkyeong Date: Mon, 10 Jul 2023 18:24:20 +0900 Subject: [PATCH 14/26] =?UTF-8?q?refactor:=20ProductService=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81(#354)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/service/ProductService.java | 311 +---------------- .../product/service/ProductServiceImpl.java | 326 ++++++++++++++++++ 2 files changed, 345 insertions(+), 292 deletions(-) create mode 100644 src/main/java/project/trendpick_pro/domain/product/service/ProductServiceImpl.java diff --git a/src/main/java/project/trendpick_pro/domain/product/service/ProductService.java b/src/main/java/project/trendpick_pro/domain/product/service/ProductService.java index 0ec76826..77140f4f 100644 --- a/src/main/java/project/trendpick_pro/domain/product/service/ProductService.java +++ b/src/main/java/project/trendpick_pro/domain/product/service/ProductService.java @@ -1,324 +1,51 @@ package project.trendpick_pro.domain.product.service; -import com.amazonaws.services.s3.AmazonS3; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; -import project.trendpick_pro.domain.brand.entity.Brand; -import project.trendpick_pro.domain.brand.service.BrandService; -import project.trendpick_pro.domain.category.entity.MainCategory; -import project.trendpick_pro.domain.category.entity.SubCategory; -import project.trendpick_pro.domain.category.service.MainCategoryService; -import project.trendpick_pro.domain.category.service.SubCategoryService; -import project.trendpick_pro.domain.common.base.filetranslator.FileTranslator; -import project.trendpick_pro.domain.common.base.rq.Rq; -import project.trendpick_pro.domain.common.file.CommonFile; import project.trendpick_pro.domain.member.entity.Member; -import project.trendpick_pro.domain.member.entity.RoleType; import project.trendpick_pro.domain.product.entity.dto.ProductRequest; import project.trendpick_pro.domain.product.entity.product.Product; -import project.trendpick_pro.domain.product.entity.product.ProductStatus; -import project.trendpick_pro.domain.product.entity.product.dto.request.ProductSaveRequest; -import project.trendpick_pro.domain.product.entity.product.dto.request.ProductSearchCond; import project.trendpick_pro.domain.product.entity.product.dto.response.*; import project.trendpick_pro.domain.product.entity.productOption.ProductOption; -import project.trendpick_pro.domain.product.entity.productOption.dto.ProductOptionSaveRequest; -import project.trendpick_pro.domain.product.exception.ProductNotFoundException; -import project.trendpick_pro.domain.product.repository.ProductRepository; -import project.trendpick_pro.domain.tags.favoritetag.entity.FavoriteTag; -import project.trendpick_pro.domain.tags.favoritetag.service.FavoriteTagService; -import project.trendpick_pro.domain.tags.tag.entity.Tag; -import project.trendpick_pro.domain.tags.tag.service.TagService; -import project.trendpick_pro.domain.tags.type.TagType; import project.trendpick_pro.global.rsData.RsData; -//import project.trendpick_pro.global.search.service.SearchService; + import java.io.IOException; import java.util.*; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; -@Slf4j -@Service -@RequiredArgsConstructor -public class ProductService { - - private final ProductRepository productRepository; - - private final MainCategoryService mainCategoryService; - private final SubCategoryService subCategoryService; - private final BrandService brandService; - - private final FileTranslator fileTranslator; - private final FavoriteTagService favoriteTagService; - private final TagService tagService; - - private final Rq rq; -// private final SearchService searchService; - - private final AmazonS3 amazonS3; - - @Value("${cloud.aws.s3.bucket}") - private String bucket; - - @Value("https://kr.object.ncloudstorage.com/{cloud.aws.s3.bucket}/") - private String filePath; - - @Transactional - public RsData register(ProductRequest request, MultipartFile requestMainFile, List requestSubFiles) throws IOException, ExecutionException, InterruptedException { - - rq.checkAdmin(); - - ProductSaveRequest productSaveRequest = request.getRequest1(); - ProductOptionSaveRequest optionSaveRequest = request.getRequest2(); - - CommonFile mainFile = fileTranslator.translateFile(requestMainFile); - List subFiles = fileTranslator.translateFileList(requestSubFiles); - - for (CommonFile subFile : subFiles) { - mainFile.connectFile(subFile); - } - - Set tags = new LinkedHashSet<>(); - for (String tagName : productSaveRequest.getTags()) { - tags.add(new Tag(tagName)); - } - - CompletableFuture mainCategoryFuture = CompletableFuture.supplyAsync(() -> mainCategoryService.findByName(productSaveRequest.getMainCategory())); - CompletableFuture subCategoryFuture = CompletableFuture.supplyAsync(() -> subCategoryService.findByName(productSaveRequest.getSubCategory())); - CompletableFuture brandFuture = CompletableFuture.supplyAsync(() -> brandService.findByName(productSaveRequest.getBrand())); - - CompletableFuture.allOf(mainCategoryFuture, subCategoryFuture, brandFuture).join(); - - MainCategory mainCategory = mainCategoryFuture.get(); - SubCategory subCategory = subCategoryFuture.get(); - Brand brand = brandFuture.get(); - - ProductOption productOption = ProductOption.of(optionSaveRequest); - productOption.connectStatus(ProductStatus.SALE); - Product product = Product.of(productSaveRequest, mainCategory, subCategory, brand, mainFile, productOption); - product.addTag(tags); - - Product saveProduct = productRepository.save(product); -// searchService.createProduct(saveProduct); - return RsData.of("S-1", "상품 등록이 완료되었습니다.", saveProduct.getId()); - } - - @Transactional - public RsData modify(Long productId, ProductRequest productRequest, MultipartFile requestMainFile, List requestSubFiles) throws IOException { - - rq.checkAdmin(); - - ProductSaveRequest productSaveRequest = productRequest.getRequest1(); - ProductOptionSaveRequest optionSaveRequest = productRequest.getRequest2(); - - Product product = productRepository.findById(productId).orElseThrow(() -> new ProductNotFoundException("존재하지 않는 상품입니다.")); - - product.getFile().deleteFile(amazonS3, bucket); - product.disconnectFile(); - - CommonFile mainFile = fileTranslator.translateFile(requestMainFile); - List subFiles = fileTranslator.translateFileList(requestSubFiles); - - for (CommonFile subFile : subFiles) { - mainFile.connectFile(subFile); - } - - Set tags = new LinkedHashSet<>(); - for (String tagName : productSaveRequest.getTags()) { - tags.add(new Tag(tagName)); - } - - tagService.delete(product.getTags()); - product.modifyTag(tags); - product.update(productSaveRequest, optionSaveRequest, mainFile); -// searchService.modifyProduct(product); - return RsData.of("S-1", "상품 수정 완료되었습니다.", product.getId()); - } - - @Transactional - public void delete(Long productId) { - rq.getAdmin(); - Product product = productRepository.findById(productId).orElseThrow(() -> new ProductNotFoundException("존재하지 않는 상품입니다.")); - product.getFile().deleteFile(amazonS3, bucket); -// searchService.deleteProduct(product); - productRepository.delete(product); - } - - @Cacheable(value = "product", key = "#productId") - @Transactional(readOnly = true) - public ProductResponse getProduct(Long productId) { - - Product product = productRepository.findById(productId).orElseThrow(() -> new ProductNotFoundException("존재하지 않는 상품입니다.")); - - if(rq.checkLogin()){ - if(rq.checkMember()){ - updateFavoriteTag(product); - } - } - - return ProductResponse.of(product); - } - - @Transactional(readOnly = true) - public ProductListResponse getProducts(Long productId) { - Product product = productRepository.findById(productId).orElseThrow(() -> new ProductNotFoundException("존재하지 않는 상품입니다.")); - return ProductListResponse.of(product); - } - - private void updateFavoriteTag(Product product) { - Member member = rq.getMember(); - if(member.getRole().equals(RoleType.MEMBER)) - favoriteTagService.updateTag(member, product, TagType.SHOW); - } - - @Transactional - @CacheEvict(value = "product", key = "#productId") - public void deleteCache(ProductOption productOption) { - productOption.connectStatus(ProductStatus.SOLD_OUT); - } - - @Transactional(readOnly = true) - public Page getProducts(int offset, String mainCategory, String subCategory) { - - ProductSearchCond cond = new ProductSearchCond(mainCategory, subCategory); - PageRequest pageable = PageRequest.of(offset, 18); - - Page listResponses = productRepository.findAllByCategoryId(cond, pageable); - - List list = listResponses.getContent().stream() - .map(product -> getProducts(product.getId())) - .peek(product -> { - String updatedMainFile = product.getMainFile(); - product.setMainFile(updatedMainFile); - }).toList(); - - return new PageImpl<>(list, pageable, listResponses.getTotalElements()); - } - - @Transactional(readOnly = true) - public Page findAllByKeyword(String keyword, int offset) { - - ProductSearchCond cond = new ProductSearchCond(keyword); - PageRequest pageable = PageRequest.of(offset, 18); - - Page listResponses = productRepository.findAllByKeyword(cond, pageable); - - List list = listResponses.getContent().stream() - .map(product -> getProducts(product.getId())) - .peek(product -> { - String updatedMainFile = product.getMainFile(); - product.setMainFile(updatedMainFile); - }).toList(); - - return new PageImpl<>(list, pageable, listResponses.getTotalElements()); - } - - @Transactional(readOnly = true) - public Page getAllProducts(Pageable pageable) { - pageable = PageRequest.of(pageable.getPageNumber(), 18); - Page products = productRepository.findAll(pageable); - return products.map(this::convertToProductListResponse); - } - @Transactional(readOnly = true) - public List getRecommendProduct(Member member) { +public interface ProductService { - List tags = productRepository.findRecommendProduct(member.getUsername()); - Set memberTags = member.getTags(); + RsData register(ProductRequest request, MultipartFile requestMainFile, List requestSubFiles) throws IOException, ExecutionException, InterruptedException; + RsData modify(Long productId, ProductRequest productRequest, MultipartFile requestMainFile, List requestSubFiles) throws IOException; - //태그명에 따라 가지고 있는 product_id - // : 멤버 태그명에 따라 해당 상품에 점수를 부여해야 하기 때문에 - Map> productIdListByTagName = new HashMap<>(); + void delete(Long productId); - //상품 id 중복을 없애기 위함 - //맴버의 태그명과 여러개가 겹쳐서 여러개의 추천상품이 반환되었을것 그 중복을 없애야 한다. - Map recommendProductByProductId = new HashMap<>(); + ProductResponse getProduct(Long productId); - //같은 태그명을 가지고 있지만 제각각 상품을 가르키는 productId는 다를 것이다. 그래서 태그명 별로 어떤 상품들을 가르키는지 모아보자 - for (ProductByRecommended tag : tags) { - if (!productIdListByTagName.containsKey(tag.getTagName())) - productIdListByTagName.put(tag.getTagName(), new ArrayList<>()); - productIdListByTagName.get(tag.getTagName()).add(tag.getProductId()); - } + ProductListResponse getProducts(Long productId); - //마찬가지로 같은 상품을 가르키고 있지만 태그명은 제각각일 것이다. 우리가 뽑아내길 원하는 것은 추천상품이다. 즉 같은 상품이 중복되면 안된다. - //그래서 상품Id에 대한 중복을 없애서 하나에 몰아넣는 코드이다. - for (ProductByRecommended response : tags) { - if (recommendProductByProductId.containsKey(response.getProductId())) - continue; - recommendProductByProductId.put(response.getProductId(), response); - } + void updateFavoriteTag(Product product); - //실제로직! member 선호태그에는 점수가 있을 것이다. - //그러니까 우리가 반환하려고 하는 추천상품이 점수가 몇점인지 갱신하는 코드이다. - for (FavoriteTag memberTag : memberTags) { - if (productIdListByTagName.containsKey(memberTag.getName())) { - List productIdList = productIdListByTagName.get(memberTag.getName()); - for (Long id : productIdList) { - recommendProductByProductId.get(id).plusTotalScore(memberTag.getScore()); - } - } - } + void deleteCache(ProductOption productOption); - List recommendProductList = new ArrayList<>(recommendProductByProductId.values()).stream() - .sorted(Comparator.comparing(ProductByRecommended::getTotalScore).reversed()) - .toList(); + Page getProducts(int offset, String mainCategory, String subCategory); - //Product 변환해서 리턴 - List products = new ArrayList<>(); - for (ProductByRecommended recommendProduct : recommendProductList) { - products.add(productRepository.findById(recommendProduct.getProductId()).orElseThrow( - () -> new ProductNotFoundException("존재하지 않는 상품입니다.") - )); - } - return products; - } + Page findAllByKeyword(String keyword, int offset); - @Transactional(readOnly = true) - public RsData> findProductsBySeller(Member member, int offset) { - if (member.getBrand() == null) - RsData.of("F-1", "브랜드 관리자의 브랜드를 알 수 없습니다. 브랜드를 설정하세요."); + Page getAllProducts(Pageable pageable); - Pageable pageable = PageRequest.of(offset, 20); - return RsData.of("S-1", "성공", productRepository.findAllBySeller(member.getBrand(), pageable)); - } + List getRecommendProduct(Member member); - @Transactional - public void applyDiscount(Long productId, double discountRate) { - Product product = productRepository.findById(productId).orElseThrow(() -> new ProductNotFoundException("존재하지 않는 상품입니다.")); - product.applyDiscount(discountRate); - } + RsData> findProductsBySeller(Member member, int offset); - private ProductListResponse convertToProductListResponse(Product product) { - return new ProductListResponse( - product.getId(), - product.getName(), - product.getBrand().getName(), - product.getFile().getFileName(), - product.getProductOption().getPrice(), - product.getDiscountRate(), - product.getDiscountedPrice() - ); - } + void applyDiscount(Long productId, double discountRate); - @Transactional(readOnly = true) - public Product findById(Long id) { - return productRepository.findById(id).orElseThrow(() -> new ProductNotFoundException("존재하지 않는 상품입니다.")); - } + ProductListResponse convertToProductListResponse(Product product); - @Transactional(readOnly = true) - public Product findByIdWithBrand(Long productId) { - return productRepository.findByIdWithBrand(productId); - } -} + Product findById(Long id); + Product findByIdWithBrand(Long productId); +} \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/domain/product/service/ProductServiceImpl.java b/src/main/java/project/trendpick_pro/domain/product/service/ProductServiceImpl.java new file mode 100644 index 00000000..1e6c6979 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/product/service/ProductServiceImpl.java @@ -0,0 +1,326 @@ +package project.trendpick_pro.domain.product.service; + +import com.amazonaws.services.s3.AmazonS3; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import project.trendpick_pro.domain.brand.entity.Brand; +import project.trendpick_pro.domain.brand.service.BrandService; +import project.trendpick_pro.domain.category.entity.MainCategory; +import project.trendpick_pro.domain.category.entity.SubCategory; +import project.trendpick_pro.domain.category.service.MainCategoryService; +import project.trendpick_pro.domain.category.service.SubCategoryService; +import project.trendpick_pro.domain.common.base.filetranslator.FileTranslator; +import project.trendpick_pro.domain.common.base.rq.Rq; +import project.trendpick_pro.domain.common.file.CommonFile; +import project.trendpick_pro.domain.member.entity.Member; +import project.trendpick_pro.domain.member.entity.RoleType; +import project.trendpick_pro.domain.product.entity.dto.ProductRequest; +import project.trendpick_pro.domain.product.entity.product.Product; +import project.trendpick_pro.domain.product.entity.product.ProductStatus; +import project.trendpick_pro.domain.product.entity.product.dto.request.ProductSaveRequest; +import project.trendpick_pro.domain.product.entity.product.dto.request.ProductSearchCond; +import project.trendpick_pro.domain.product.entity.product.dto.response.ProductByRecommended; +import project.trendpick_pro.domain.product.entity.product.dto.response.ProductListResponse; +import project.trendpick_pro.domain.product.entity.product.dto.response.ProductListResponseBySeller; +import project.trendpick_pro.domain.product.entity.product.dto.response.ProductResponse; +import project.trendpick_pro.domain.product.entity.productOption.ProductOption; +import project.trendpick_pro.domain.product.entity.productOption.dto.ProductOptionSaveRequest; +import project.trendpick_pro.domain.product.exception.ProductNotFoundException; +import project.trendpick_pro.domain.product.repository.ProductRepository; +import project.trendpick_pro.domain.tags.favoritetag.entity.FavoriteTag; +import project.trendpick_pro.domain.tags.favoritetag.service.FavoriteTagService; +import project.trendpick_pro.domain.tags.tag.entity.Tag; +import project.trendpick_pro.domain.tags.tag.service.TagService; +import project.trendpick_pro.domain.tags.type.TagType; +import project.trendpick_pro.global.rsData.RsData; + +import java.io.IOException; +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ProductServiceImpl implements ProductService{ + + private final ProductRepository productRepository; + + private final MainCategoryService mainCategoryService; + private final SubCategoryService subCategoryService; + private final BrandService brandService; + + private final FileTranslator fileTranslator; + private final FavoriteTagService favoriteTagService; + private final TagService tagService; + + private final Rq rq; +// private final SearchService searchService; + + private final AmazonS3 amazonS3; + + @Value("${cloud.aws.s3.bucket}") + private String bucket; + + @Value("https://kr.object.ncloudstorage.com/{cloud.aws.s3.bucket}/") + private String filePath; + + @Transactional + public RsData register(ProductRequest request, MultipartFile requestMainFile, List requestSubFiles) throws IOException, ExecutionException, InterruptedException { + + rq.checkAdmin(); + + ProductSaveRequest productSaveRequest = request.getRequest1(); + ProductOptionSaveRequest optionSaveRequest = request.getRequest2(); + + CommonFile mainFile = fileTranslator.translateFile(requestMainFile); + List subFiles = fileTranslator.translateFileList(requestSubFiles); + + for (CommonFile subFile : subFiles) { + mainFile.connectFile(subFile); + } + + Set tags = new LinkedHashSet<>(); + for (String tagName : productSaveRequest.getTags()) { + tags.add(new Tag(tagName)); + } + + CompletableFuture mainCategoryFuture = CompletableFuture.supplyAsync(() -> mainCategoryService.findByName(productSaveRequest.getMainCategory())); + CompletableFuture subCategoryFuture = CompletableFuture.supplyAsync(() -> subCategoryService.findByName(productSaveRequest.getSubCategory())); + CompletableFuture brandFuture = CompletableFuture.supplyAsync(() -> brandService.findByName(productSaveRequest.getBrand())); + + CompletableFuture.allOf(mainCategoryFuture, subCategoryFuture, brandFuture).join(); + + MainCategory mainCategory = mainCategoryFuture.get(); + SubCategory subCategory = subCategoryFuture.get(); + Brand brand = brandFuture.get(); + + ProductOption productOption = ProductOption.of(optionSaveRequest); + productOption.connectStatus(ProductStatus.SALE); + Product product = Product.of(productSaveRequest, mainCategory, subCategory, brand, mainFile, productOption); + product.addTag(tags); + + Product saveProduct = productRepository.save(product); +// searchService.createProduct(saveProduct); + return RsData.of("S-1", "상품 등록이 완료되었습니다.", saveProduct.getId()); + } + + @Transactional + public RsData modify(Long productId, ProductRequest productRequest, MultipartFile requestMainFile, List requestSubFiles) throws IOException { + + rq.checkAdmin(); + + ProductSaveRequest productSaveRequest = productRequest.getRequest1(); + ProductOptionSaveRequest optionSaveRequest = productRequest.getRequest2(); + + Product product = productRepository.findById(productId).orElseThrow(() -> new ProductNotFoundException("존재하지 않는 상품입니다.")); + + product.getFile().deleteFile(amazonS3, bucket); + product.disconnectFile(); + + CommonFile mainFile = fileTranslator.translateFile(requestMainFile); + List subFiles = fileTranslator.translateFileList(requestSubFiles); + + for (CommonFile subFile : subFiles) { + mainFile.connectFile(subFile); + } + + Set tags = new LinkedHashSet<>(); + for (String tagName : productSaveRequest.getTags()) { + tags.add(new Tag(tagName)); + } + + tagService.delete(product.getTags()); + product.modifyTag(tags); + product.update(productSaveRequest, optionSaveRequest, mainFile); +// searchService.modifyProduct(product); + return RsData.of("S-1", "상품 수정 완료되었습니다.", product.getId()); + } + + @Transactional + public void delete(Long productId) { + rq.getAdmin(); + Product product = productRepository.findById(productId).orElseThrow(() -> new ProductNotFoundException("존재하지 않는 상품입니다.")); + product.getFile().deleteFile(amazonS3, bucket); +// searchService.deleteProduct(product); + productRepository.delete(product); + } + + @Cacheable(value = "product", key = "#productId") + @Transactional(readOnly = true) + public ProductResponse getProduct(Long productId) { + + Product product = productRepository.findById(productId).orElseThrow(() -> new ProductNotFoundException("존재하지 않는 상품입니다.")); + + if(rq.checkLogin()){ + if(rq.checkMember()){ + updateFavoriteTag(product); + } + } + + return ProductResponse.of(product); + } + + @Transactional(readOnly = true) + public ProductListResponse getProducts(Long productId) { + Product product = productRepository.findById(productId).orElseThrow(() -> new ProductNotFoundException("존재하지 않는 상품입니다.")); + return ProductListResponse.of(product); + } + + public void updateFavoriteTag(Product product) { + Member member = rq.getMember(); + if(member.getRole().equals(RoleType.MEMBER)) + favoriteTagService.updateTag(member, product, TagType.SHOW); + } + + @Transactional + @CacheEvict(value = "product", key = "#productId") + public void deleteCache(ProductOption productOption) { + productOption.connectStatus(ProductStatus.SOLD_OUT); + } + + @Transactional(readOnly = true) + public Page getProducts(int offset, String mainCategory, String subCategory) { + + ProductSearchCond cond = new ProductSearchCond(mainCategory, subCategory); + PageRequest pageable = PageRequest.of(offset, 18); + + Page listResponses = productRepository.findAllByCategoryId(cond, pageable); + + List list = listResponses.getContent().stream() + .map(product -> getProducts(product.getId())) + .peek(product -> { + String updatedMainFile = product.getMainFile(); + product.setMainFile(updatedMainFile); + }).toList(); + + return new PageImpl<>(list, pageable, listResponses.getTotalElements()); + } + + @Transactional(readOnly = true) + public Page findAllByKeyword(String keyword, int offset) { + + ProductSearchCond cond = new ProductSearchCond(keyword); + PageRequest pageable = PageRequest.of(offset, 18); + + Page listResponses = productRepository.findAllByKeyword(cond, pageable); + + List list = listResponses.getContent().stream() + .map(product -> getProducts(product.getId())) + .peek(product -> { + String updatedMainFile = product.getMainFile(); + product.setMainFile(updatedMainFile); + }).toList(); + + return new PageImpl<>(list, pageable, listResponses.getTotalElements()); + } + + @Transactional(readOnly = true) + public Page getAllProducts(Pageable pageable) { + pageable = PageRequest.of(pageable.getPageNumber(), 18); + Page products = productRepository.findAll(pageable); + return products.map(this::convertToProductListResponse); + } + + @Transactional(readOnly = true) + public List getRecommendProduct(Member member) { + + List tags = productRepository.findRecommendProduct(member.getUsername()); + Set memberTags = member.getTags(); + + + //태그명에 따라 가지고 있는 product_id + // : 멤버 태그명에 따라 해당 상품에 점수를 부여해야 하기 때문에 + Map> productIdListByTagName = new HashMap<>(); + + //상품 id 중복을 없애기 위함 + //맴버의 태그명과 여러개가 겹쳐서 여러개의 추천상품이 반환되었을것 그 중복을 없애야 한다. + Map recommendProductByProductId = new HashMap<>(); + + //같은 태그명을 가지고 있지만 제각각 상품을 가르키는 productId는 다를 것이다. 그래서 태그명 별로 어떤 상품들을 가르키는지 모아보자 + for (ProductByRecommended tag : tags) { + if (!productIdListByTagName.containsKey(tag.getTagName())) + productIdListByTagName.put(tag.getTagName(), new ArrayList<>()); + productIdListByTagName.get(tag.getTagName()).add(tag.getProductId()); + } + + //마찬가지로 같은 상품을 가르키고 있지만 태그명은 제각각일 것이다. 우리가 뽑아내길 원하는 것은 추천상품이다. 즉 같은 상품이 중복되면 안된다. + //그래서 상품Id에 대한 중복을 없애서 하나에 몰아넣는 코드이다. + for (ProductByRecommended response : tags) { + if (recommendProductByProductId.containsKey(response.getProductId())) + continue; + recommendProductByProductId.put(response.getProductId(), response); + } + + //실제로직! member 선호태그에는 점수가 있을 것이다. + //그러니까 우리가 반환하려고 하는 추천상품이 점수가 몇점인지 갱신하는 코드이다. + for (FavoriteTag memberTag : memberTags) { + if (productIdListByTagName.containsKey(memberTag.getName())) { + List productIdList = productIdListByTagName.get(memberTag.getName()); + for (Long id : productIdList) { + recommendProductByProductId.get(id).plusTotalScore(memberTag.getScore()); + } + } + } + + List recommendProductList = new ArrayList<>(recommendProductByProductId.values()).stream() + .sorted(Comparator.comparing(ProductByRecommended::getTotalScore).reversed()) + .toList(); + + //Product 변환해서 리턴 + List products = new ArrayList<>(); + for (ProductByRecommended recommendProduct : recommendProductList) { + products.add(productRepository.findById(recommendProduct.getProductId()).orElseThrow( + () -> new ProductNotFoundException("존재하지 않는 상품입니다.") + )); + } + return products; + } + + @Transactional(readOnly = true) + public RsData> findProductsBySeller(Member member, int offset) { + if (member.getBrand() == null) + RsData.of("F-1", "브랜드 관리자의 브랜드를 알 수 없습니다. 브랜드를 설정하세요."); + + Pageable pageable = PageRequest.of(offset, 20); + return RsData.of("S-1", "성공", productRepository.findAllBySeller(member.getBrand(), pageable)); + } + + @Transactional + public void applyDiscount(Long productId, double discountRate) { + Product product = productRepository.findById(productId).orElseThrow(() -> new ProductNotFoundException("존재하지 않는 상품입니다.")); + product.applyDiscount(discountRate); + } + + public ProductListResponse convertToProductListResponse(Product product) { + return new ProductListResponse( + product.getId(), + product.getName(), + product.getBrand().getName(), + product.getFile().getFileName(), + product.getProductOption().getPrice(), + product.getDiscountRate(), + product.getDiscountedPrice() + ); + } + + @Transactional(readOnly = true) + public Product findById(Long id) { + return productRepository.findById(id).orElseThrow(() -> new ProductNotFoundException("존재하지 않는 상품입니다.")); + } + + @Transactional(readOnly = true) + public Product findByIdWithBrand(Long productId) { + return productRepository.findByIdWithBrand(productId); + } +} \ No newline at end of file From f931c2ae309f1eb7b574261e2849d6325fe105a1 Mon Sep 17 00:00:00 2001 From: mmunkyeong Date: Mon, 10 Jul 2023 18:27:24 +0900 Subject: [PATCH 15/26] =?UTF-8?q?refactor:=20OrderService=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81(#354)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/orders/service/OrderService.java | 236 ++-------------- .../orders/service/OrderServiceImpl.java | 258 ++++++++++++++++++ 2 files changed, 275 insertions(+), 219 deletions(-) create mode 100644 src/main/java/project/trendpick_pro/domain/orders/service/OrderServiceImpl.java diff --git a/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java b/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java index 571e156f..bcd7cf21 100644 --- a/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java +++ b/src/main/java/project/trendpick_pro/domain/orders/service/OrderService.java @@ -1,29 +1,13 @@ package project.trendpick_pro.domain.orders.service; import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; -import org.springframework.kafka.annotation.KafkaListener; -import org.springframework.kafka.core.KafkaTemplate; import org.springframework.messaging.handler.annotation.Payload; -import org.springframework.messaging.simp.SimpMessagingTemplate; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import project.trendpick_pro.domain.cart.entity.CartItem; -import project.trendpick_pro.domain.cart.service.CartService; -import project.trendpick_pro.domain.delivery.entity.Delivery; -import project.trendpick_pro.domain.delivery.entity.DeliveryState; import project.trendpick_pro.domain.member.entity.Member; import project.trendpick_pro.domain.orders.entity.Order; import project.trendpick_pro.domain.orders.entity.OrderItem; -import project.trendpick_pro.domain.orders.entity.OrderStatus; import project.trendpick_pro.domain.orders.entity.dto.request.CartToOrderRequest; -import project.trendpick_pro.domain.orders.entity.dto.request.OrderSearchCond; -import project.trendpick_pro.domain.orders.entity.dto.request.OrderStateResponse; + import project.trendpick_pro.domain.orders.entity.dto.response.OrderDetailResponse; import project.trendpick_pro.domain.orders.entity.dto.response.OrderResponse; import project.trendpick_pro.domain.orders.exceoption.OrderNotFoundException; @@ -37,223 +21,37 @@ import project.trendpick_pro.domain.tags.type.TagType; import project.trendpick_pro.global.rsData.RsData; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.UUID; +import java.util.List; import java.time.LocalDateTime; -@Slf4j -@Service -@Transactional(readOnly = true) -@RequiredArgsConstructor -public class OrderService { - private final OrderItemRepository orderItemRepository; - - private final OrderRepository orderRepository; - - private final CartService cartService; - private final ProductService productService; - private final FavoriteTagService favoriteTagService; - - private final KafkaTemplate kafkaTemplate; - private final SimpMessagingTemplate messagingTemplate; - private final ObjectMapper objectMapper; - - @Transactional - public RsData cartToOrder(Member member, CartToOrderRequest request) { - - if(member.getAddress().trim().length() == 0) { - return RsData.of("F-1", "주소를 알 수 없어 주문이 불가능합니다."); - } - if(request.getSelectedItems().isEmpty()){ - return RsData.of("F-1","상품을 선택한 후 주문해주세요."); - } - - List cartItems = cartService.findCartItems(member, request); - if (!Objects.equals(cartItems.get(0).getCart().getMember().getId(), member.getId())) { - return RsData.of("F-1", "현재 접속중인 사용자와 장바구니 사용자가 일치하지 않습니다."); - } - - List orderItemList = new ArrayList<>(); - for (CartItem cartItem : cartItems) { - Product product = productService.findById(cartItem.getProduct().getId()); - if (product.getProductOption().getStock() < cartItem.getQuantity()) { - RsData.of("F-2", product.getName()+"의 재고가 부족합니다."); - } - favoriteTagService.updateTag(member, product, TagType.ORDER); - orderItemList.add(OrderItem.of(product, cartItem)); - } - - Order order = Order.createOrder(member, new Delivery(member.getAddress()), OrderStatus.TEMP, orderItemList, cartItems); - Order saveOrder = orderRepository.save(order); - - kafkaTemplate.send("orders", String.valueOf(saveOrder.getId()), String.valueOf(saveOrder.getId())); - - return RsData.of("S-1", "주문을 시작합니다.", saveOrder); - } - - @Transactional - public RsData productToOrder(Member member, Long id, int quantity, String size, String color) { - try { - Product product = productService.findById(id); - OrderItem orderItem = OrderItem.of(product, quantity, size, color); - - Order order = Order.createOrder(member, new Delivery(member.getAddress()), OrderStatus.TEMP, orderItem); - Order saveOrder = orderRepository.save(order); - - kafkaTemplate.send("orders", String.valueOf(saveOrder.getId()), String.valueOf(saveOrder.getId())); - - return RsData.of("S-1", "주문을 시작합니다.", saveOrder); - } catch (ProductNotFoundException e) { - return RsData.of("F-1", "존재하지 않는 상품입니다."); - } - } - - @Transactional - @KafkaListener(topicPattern = "orders", groupId = "group_id") - public void orderToOrder(@Payload String Id) throws JsonProcessingException { - try { - Thread.sleep(750); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Order order = orderRepository.findById(Long.valueOf(Id)).orElseThrow(() -> new OrderNotFoundException("존재하지 않는 주문입니다.")); - Member member = order.getMember(); - try { - for (OrderItem orderItem : order.getOrderItems()) { - orderItem.getProduct().getProductOption().decreaseStock(orderItem.getQuantity()); - if (orderItem.getProduct().getProductOption().getStock() == 0) { - productService.deleteCache(orderItem.getProduct().getProductOption()); - } - } - order.modifyStatus(OrderStatus.ORDERED); - sendMessage("Success", order.getId(), member.getEmail()); - } catch (ProductStockOutException e) { - order.cancelTemp(); - sendMessage("Fail", order.getId(), member.getEmail()); - } - } - - public void sendMessage(String message, Long orderId, String email) throws JsonProcessingException { - - OrderStateResponse response = OrderStateResponse.builder() - .orderId(orderId) - .message(message) - .email(email) - .build(); - - String json = objectMapper.writeValueAsString(response); - kafkaTemplate.send("standByOrder", UUID.randomUUID().toString(), json); - } - - @KafkaListener(topicPattern = "standByOrder", groupId = "#{T(java.util.UUID).randomUUID().toString()}") - public void message(@Payload String json) throws JsonProcessingException { - OrderStateResponse response = objectMapper.readValue(json, OrderStateResponse.class); - messagingTemplate.convertAndSendToUser(response.getEmail(), "/topic/standByOrder", json); - } - - @Transactional - public RsData cancel(Long orderId) { - Order order = orderRepository.findById(orderId).orElseThrow(() -> new OrderNotFoundException("존재하지 않는 주문입니다.")); - if(order.getStatus() == OrderStatus.CANCELED) { - return RsData.of("F-1", "이미 취소된 주문입니다."); - } else if (order.getDelivery().getState() == DeliveryState.COMPLETED) { - return RsData.of("F-2", "이미 배송완료된 상품은 취소가 불가능합니다."); - } - if (order.getDelivery().getState() == DeliveryState.DELIVERY_ING) { - return RsData.of("F-3", "이미 배송을 시작하여 취소가 불가능합니다."); - } - order.cancel(); - return RsData.of("S-1", "환불 요청이 정상적으로 진행되었습니다. 환불까지는 최소 2일에서 최대 14일까지 소요될 수 있습니다."); - } - - @Transactional - public void delete(Long id) { - Order order = orderRepository.findById(id).orElseThrow(() -> new OrderNotFoundException("존재하지 않는 주문입니다.")); - orderRepository.delete(order); - } - - public RsData showOrderItems(Member member, Long orderId) { - try { - Order order = orderRepository.findById(orderId).orElseThrow(() -> new OrderNotFoundException("존재하지 않는 주문입니다.")); - if (order.getStatus() == OrderStatus.TEMP) { - orderRepository.delete(order); - return RsData.of("F-3", "존재하지 않는 주문입니다."); - } - if (!Objects.equals(order.getMember().getId(), member.getId())) { - return RsData.of("F-2", "다른 사용자의 주문에는 접근할 수 없습니다."); - } - OrderDetailResponse orderResponse = OrderDetailResponse.of(order, orderRepository.findOrderItemsByOrderId(orderId)); - return RsData.of("S-1", orderResponse.getOrderItems().size()+" 개의 주문 상품입니다.", orderResponse); - } catch (OrderNotFoundException e) { - return RsData.of("F-1", "잘못된 주문번호입니다. 다시 확인해주세요."); - } - } - - public Page findAllByMember(Member member, int offset) { - Page allByMember = orderRepository.findAllByMember(new OrderSearchCond(member.getId()), PageRequest.of(offset, 10)); - - List validOrders = new ArrayList<>(); - for (OrderResponse orderResponse : allByMember.getContent()) { - Order order = orderRepository.findById(orderResponse.getOrderId()).orElseThrow(() -> new OrderNotFoundException("존재하지 않는 주문입니다.")); - if (order.getStatus() != OrderStatus.TEMP) { - validOrders.add(orderResponse); - } - } - // 변환 - List modifiableList = new ArrayList<>(allByMember.getContent()); +public interface OrderService { + RsData cartToOrder(Member member, CartToOrderRequest request); - // 삭제 대상인 임시 주문 필터링 - modifiableList.removeIf(orderResponse -> !validOrders.contains(orderResponse)); - return new PageImpl<>(modifiableList, allByMember.getPageable(), modifiableList.size()); - } + RsData productToOrder(Member member, Long id, int quantity, String size, String color); + void orderToOrder(@Payload String Id)throws JsonProcessingException ; - public Page findAllBySeller(Member member, int offset) { - Page allBySeller = orderRepository.findAllBySeller(new OrderSearchCond(member.getBrand()), PageRequest.of(offset, 10)); + void sendMessage(String message, Long orderId, String email)throws JsonProcessingException; - List validOrders = new ArrayList<>(); - for (OrderResponse orderResponse : allBySeller.getContent()) { - Order order = orderRepository.findById(orderResponse.getOrderId()).orElseThrow(() -> new OrderNotFoundException("존재하지 않는 주문입니다.")); - if (order.getStatus() != OrderStatus.TEMP) { - validOrders.add(orderResponse); - } - } + void message(@Payload String json)throws JsonProcessingException; - // 변환 - List modifiableList = new ArrayList<>(allBySeller.getContent()); + RsData cancel(Long orderId); - // 삭제 대상인 임시 주문 필터링 - modifiableList.removeIf(orderResponse -> !validOrders.contains(orderResponse)); - return new PageImpl<>(modifiableList, allBySeller.getPageable(), modifiableList.size()); - } + void delete(Long id); - public int settlementOfSales(Member member) { - int totalPrice = 0; + RsData showOrderItems(Member member, Long orderId); - List ordersPerMonth = orderRepository.findAllByMonth(new OrderSearchCond(member.getBrand())); + Page findAllByMember(Member member, int offset); - for(OrderResponse op : ordersPerMonth){ - if(op.getOrderStatus().equals("ORDERED")){ - totalPrice += op.getTotalPrice(); - } - } + Page findAllBySeller(Member member, int offset); - return totalPrice; - } + int settlementOfSales(Member member); - public Order findById(Long id) { - return orderRepository.findById(id).orElseThrow(() -> new OrderNotFoundException("존재하지 않는 주문입니다.")); - } + Order findById(Long id); - public Page findCanceledOrders(Member member, int offset) { - return orderRepository.findAllByMember(new OrderSearchCond(member.getId(), OrderStatus.CANCELED), PageRequest.of(offset, 10)); - } - public List findAllByPayDateBetweenOrderByIdAsc(LocalDateTime fromDate, LocalDateTime toDate) { - return orderItemRepository.findAllByPayDateBetween(fromDate, toDate); - } + Page findCanceledOrders(Member member, int offset); + List findAllByPayDateBetweenOrderByIdAsc(LocalDateTime fromDate, LocalDateTime toDate); } \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/domain/orders/service/OrderServiceImpl.java b/src/main/java/project/trendpick_pro/domain/orders/service/OrderServiceImpl.java new file mode 100644 index 00000000..64512b92 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/orders/service/OrderServiceImpl.java @@ -0,0 +1,258 @@ +package project.trendpick_pro.domain.orders.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.messaging.handler.annotation.Payload; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.cart.entity.CartItem; +import project.trendpick_pro.domain.cart.service.CartService; +import project.trendpick_pro.domain.delivery.entity.Delivery; +import project.trendpick_pro.domain.delivery.entity.DeliveryState; +import project.trendpick_pro.domain.member.entity.Member; +import project.trendpick_pro.domain.orders.entity.Order; +import project.trendpick_pro.domain.orders.entity.OrderItem; +import project.trendpick_pro.domain.orders.entity.OrderStatus; +import project.trendpick_pro.domain.orders.entity.dto.request.CartToOrderRequest; +import project.trendpick_pro.domain.orders.entity.dto.request.OrderSearchCond; +import project.trendpick_pro.domain.orders.entity.dto.request.OrderStateResponse; +import project.trendpick_pro.domain.orders.entity.dto.response.OrderDetailResponse; +import project.trendpick_pro.domain.orders.entity.dto.response.OrderResponse; +import project.trendpick_pro.domain.orders.exceoption.OrderNotFoundException; +import project.trendpick_pro.domain.orders.repository.OrderItemRepository; +import project.trendpick_pro.domain.orders.repository.OrderRepository; +import project.trendpick_pro.domain.product.entity.product.Product; +import project.trendpick_pro.domain.product.exception.ProductNotFoundException; +import project.trendpick_pro.domain.product.exception.ProductStockOutException; +import project.trendpick_pro.domain.product.service.ProductService; +import project.trendpick_pro.domain.tags.favoritetag.service.FavoriteTagService; +import project.trendpick_pro.domain.tags.type.TagType; +import project.trendpick_pro.global.rsData.RsData; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +@Slf4j +@Service +@RequiredArgsConstructor +public class OrderServiceImpl implements OrderService{ + private final OrderItemRepository orderItemRepository; + + private final OrderRepository orderRepository; + + private final CartService cartService; + private final ProductService productService; + private final FavoriteTagService favoriteTagService; + + private final KafkaTemplate kafkaTemplate; + private final SimpMessagingTemplate messagingTemplate; + private final ObjectMapper objectMapper; + + @Transactional + public RsData cartToOrder(Member member, CartToOrderRequest request) { + + if(member.getAddress().trim().length() == 0) { + return RsData.of("F-1", "주소를 알 수 없어 주문이 불가능합니다."); + } + if(request.getSelectedItems().isEmpty()){ + return RsData.of("F-1","상품을 선택한 후 주문해주세요."); + } + + List cartItems = cartService.findCartItems(member, request); + if (!Objects.equals(cartItems.get(0).getCart().getMember().getId(), member.getId())) { + return RsData.of("F-1", "현재 접속중인 사용자와 장바구니 사용자가 일치하지 않습니다."); + } + + List orderItemList = new ArrayList<>(); + for (CartItem cartItem : cartItems) { + Product product = productService.findById(cartItem.getProduct().getId()); + if (product.getProductOption().getStock() < cartItem.getQuantity()) { + RsData.of("F-2", product.getName()+"의 재고가 부족합니다."); + } + favoriteTagService.updateTag(member, product, TagType.ORDER); + orderItemList.add(OrderItem.of(product, cartItem)); + } + + Order order = Order.createOrder(member, new Delivery(member.getAddress()), OrderStatus.TEMP, orderItemList, cartItems); + Order saveOrder = orderRepository.save(order); + + kafkaTemplate.send("orders", String.valueOf(saveOrder.getId()), String.valueOf(saveOrder.getId())); + + return RsData.of("S-1", "주문을 시작합니다.", saveOrder); + } + + @Transactional + public RsData productToOrder(Member member, Long id, int quantity, String size, String color) { + try { + Product product = productService.findById(id); + OrderItem orderItem = OrderItem.of(product, quantity, size, color); + + Order order = Order.createOrder(member, new Delivery(member.getAddress()), OrderStatus.TEMP, orderItem); + Order saveOrder = orderRepository.save(order); + + kafkaTemplate.send("orders", String.valueOf(saveOrder.getId()), String.valueOf(saveOrder.getId())); + + return RsData.of("S-1", "주문을 시작합니다.", saveOrder); + } catch (ProductNotFoundException e) { + return RsData.of("F-1", "존재하지 않는 상품입니다."); + } + } + + @Transactional + @KafkaListener(topicPattern = "orders", groupId = "group_id") + public void orderToOrder(@Payload String Id) throws JsonProcessingException { + try { + Thread.sleep(750); + } catch (InterruptedException e) { + e.printStackTrace(); + } + Order order = orderRepository.findById(Long.valueOf(Id)).orElseThrow(() -> new OrderNotFoundException("존재하지 않는 주문입니다.")); + Member member = order.getMember(); + try { + for (OrderItem orderItem : order.getOrderItems()) { + orderItem.getProduct().getProductOption().decreaseStock(orderItem.getQuantity()); + if (orderItem.getProduct().getProductOption().getStock() == 0) { + productService.deleteCache(orderItem.getProduct().getProductOption()); + } + } + order.modifyStatus(OrderStatus.ORDERED); + sendMessage("Success", order.getId(), member.getEmail()); + } catch (ProductStockOutException e) { + order.cancelTemp(); + sendMessage("Fail", order.getId(), member.getEmail()); + } + } + + public void sendMessage(String message, Long orderId, String email) throws JsonProcessingException { + + OrderStateResponse response = OrderStateResponse.builder() + .orderId(orderId) + .message(message) + .email(email) + .build(); + + String json = objectMapper.writeValueAsString(response); + kafkaTemplate.send("standByOrder", UUID.randomUUID().toString(), json); + } + + @KafkaListener(topicPattern = "standByOrder", groupId = "#{T(java.util.UUID).randomUUID().toString()}") + public void message(@Payload String json) throws JsonProcessingException { + OrderStateResponse response = objectMapper.readValue(json, OrderStateResponse.class); + messagingTemplate.convertAndSendToUser(response.getEmail(), "/topic/standByOrder", json); + } + + @Transactional + public RsData cancel(Long orderId) { + Order order = orderRepository.findById(orderId).orElseThrow(() -> new OrderNotFoundException("존재하지 않는 주문입니다.")); + if(order.getStatus() == OrderStatus.CANCELED) { + return RsData.of("F-1", "이미 취소된 주문입니다."); + } else if (order.getDelivery().getState() == DeliveryState.COMPLETED) { + return RsData.of("F-2", "이미 배송완료된 상품은 취소가 불가능합니다."); + } + if (order.getDelivery().getState() == DeliveryState.DELIVERY_ING) { + return RsData.of("F-3", "이미 배송을 시작하여 취소가 불가능합니다."); + } + order.cancel(); + return RsData.of("S-1", "환불 요청이 정상적으로 진행되었습니다. 환불까지는 최소 2일에서 최대 14일까지 소요될 수 있습니다."); + } + + @Transactional + public void delete(Long id) { + Order order = orderRepository.findById(id).orElseThrow(() -> new OrderNotFoundException("존재하지 않는 주문입니다.")); + orderRepository.delete(order); + } + @Transactional(readOnly = true) + public RsData showOrderItems(Member member, Long orderId) { + try { + Order order = orderRepository.findById(orderId).orElseThrow(() -> new OrderNotFoundException("존재하지 않는 주문입니다.")); + if (order.getStatus() == OrderStatus.TEMP) { + orderRepository.delete(order); + return RsData.of("F-3", "존재하지 않는 주문입니다."); + } + if (!Objects.equals(order.getMember().getId(), member.getId())) { + return RsData.of("F-2", "다른 사용자의 주문에는 접근할 수 없습니다."); + } + OrderDetailResponse orderResponse = OrderDetailResponse.of(order, orderRepository.findOrderItemsByOrderId(orderId)); + return RsData.of("S-1", orderResponse.getOrderItems().size()+" 개의 주문 상품입니다.", orderResponse); + } catch (OrderNotFoundException e) { + return RsData.of("F-1", "잘못된 주문번호입니다. 다시 확인해주세요."); + } + } + @Transactional(readOnly = true) + public Page findAllByMember(Member member, int offset) { + Page allByMember = orderRepository.findAllByMember(new OrderSearchCond(member.getId()), PageRequest.of(offset, 10)); + + List validOrders = new ArrayList<>(); + for (OrderResponse orderResponse : allByMember.getContent()) { + Order order = orderRepository.findById(orderResponse.getOrderId()).orElseThrow(() -> new OrderNotFoundException("존재하지 않는 주문입니다.")); + if (order.getStatus() != OrderStatus.TEMP) { + validOrders.add(orderResponse); + } + } + + // 변환 + List modifiableList = new ArrayList<>(allByMember.getContent()); + + // 삭제 대상인 임시 주문 필터링 + modifiableList.removeIf(orderResponse -> !validOrders.contains(orderResponse)); + return new PageImpl<>(modifiableList, allByMember.getPageable(), modifiableList.size()); + } + + @Transactional(readOnly = true) + public Page findAllBySeller(Member member, int offset) { + Page allBySeller = orderRepository.findAllBySeller(new OrderSearchCond(member.getBrand()), PageRequest.of(offset, 10)); + + List validOrders = new ArrayList<>(); + for (OrderResponse orderResponse : allBySeller.getContent()) { + Order order = orderRepository.findById(orderResponse.getOrderId()).orElseThrow(() -> new OrderNotFoundException("존재하지 않는 주문입니다.")); + if (order.getStatus() != OrderStatus.TEMP) { + validOrders.add(orderResponse); + } + } + + // 변환 + List modifiableList = new ArrayList<>(allBySeller.getContent()); + + // 삭제 대상인 임시 주문 필터링 + modifiableList.removeIf(orderResponse -> !validOrders.contains(orderResponse)); + return new PageImpl<>(modifiableList, allBySeller.getPageable(), modifiableList.size()); + } + + public int settlementOfSales(Member member) { + int totalPrice = 0; + + List ordersPerMonth = orderRepository.findAllByMonth(new OrderSearchCond(member.getBrand())); + + for(OrderResponse op : ordersPerMonth){ + if(op.getOrderStatus().equals("ORDERED")){ + totalPrice += op.getTotalPrice(); + } + } + + return totalPrice; + } + + @Transactional(readOnly = true) + public Order findById(Long id) { + return orderRepository.findById(id).orElseThrow(() -> new OrderNotFoundException("존재하지 않는 주문입니다.")); + } + @Transactional(readOnly = true) + public Page findCanceledOrders(Member member, int offset) { + return orderRepository.findAllByMember(new OrderSearchCond(member.getId(), OrderStatus.CANCELED), PageRequest.of(offset, 10)); + } + @Transactional(readOnly = true) + public List findAllByPayDateBetweenOrderByIdAsc(LocalDateTime fromDate, LocalDateTime toDate) { + return orderItemRepository.findAllByPayDateBetween(fromDate, toDate); + } +} From 0f4de85b97c28c5add2a80a4b9fed92a52993e1f Mon Sep 17 00:00:00 2001 From: mmunkyeong Date: Mon, 10 Jul 2023 18:28:55 +0900 Subject: [PATCH 16/26] =?UTF-8?q?refactor:=20CashService=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81(#354)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/cash/service/CashService.java | 22 +++------------- .../domain/cash/service/CashServiceImpl.java | 26 +++++++++++++++++++ 2 files changed, 29 insertions(+), 19 deletions(-) create mode 100644 src/main/java/project/trendpick_pro/domain/cash/service/CashServiceImpl.java diff --git a/src/main/java/project/trendpick_pro/domain/cash/service/CashService.java b/src/main/java/project/trendpick_pro/domain/cash/service/CashService.java index 83643848..62ed08af 100644 --- a/src/main/java/project/trendpick_pro/domain/cash/service/CashService.java +++ b/src/main/java/project/trendpick_pro/domain/cash/service/CashService.java @@ -1,27 +1,11 @@ package project.trendpick_pro.domain.cash.service; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; + import project.trendpick_pro.domain.cash.entity.CashLog; -import project.trendpick_pro.domain.cash.repository.CashLogRepository; import project.trendpick_pro.domain.member.entity.Member; -@Service -@RequiredArgsConstructor -public class CashService { - private final CashLogRepository cashLogRepository; - - public CashLog addCash(Member member, long price, String relTypeCode,Long relId, CashLog.EvenType eventType) { - CashLog cashLog = CashLog.builder() - .member(member) - .price(price) - .relTypeCode(relTypeCode) - .relId(relId) - .eventType(eventType) - .build(); - cashLogRepository.save(cashLog); +public interface CashService { + CashLog addCash(Member member, long price, String relTypeCode,Long relId, CashLog.EvenType eventType); - return cashLog; - } } \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/domain/cash/service/CashServiceImpl.java b/src/main/java/project/trendpick_pro/domain/cash/service/CashServiceImpl.java new file mode 100644 index 00000000..a5b3fda6 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/cash/service/CashServiceImpl.java @@ -0,0 +1,26 @@ +package project.trendpick_pro.domain.cash.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import project.trendpick_pro.domain.cash.entity.CashLog; +import project.trendpick_pro.domain.cash.repository.CashLogRepository; +import project.trendpick_pro.domain.member.entity.Member; +@Service +@RequiredArgsConstructor +public class CashServiceImpl implements CashService{ + private final CashLogRepository cashLogRepository; + + public CashLog addCash(Member member, long price, String relTypeCode, Long relId, CashLog.EvenType eventType) { + CashLog cashLog = CashLog.builder() + .member(member) + .price(price) + .relTypeCode(relTypeCode) + .relId(relId) + .eventType(eventType) + .build(); + + cashLogRepository.save(cashLog); + + return cashLog; + } +} From 9575a92c48a198d1701107faff08abeac1afc71c Mon Sep 17 00:00:00 2001 From: mmunkyeong Date: Mon, 10 Jul 2023 18:30:55 +0900 Subject: [PATCH 17/26] =?UTF-8?q?refactor:=20DeliveryService=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81(#354)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../delivery/service/DeliveryService.java | 17 ++--------------- .../delivery/service/DeliveryServiceImpl.java | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 15 deletions(-) create mode 100644 src/main/java/project/trendpick_pro/domain/delivery/service/DeliveryServiceImpl.java diff --git a/src/main/java/project/trendpick_pro/domain/delivery/service/DeliveryService.java b/src/main/java/project/trendpick_pro/domain/delivery/service/DeliveryService.java index a436ddd9..dcb4bfc5 100644 --- a/src/main/java/project/trendpick_pro/domain/delivery/service/DeliveryService.java +++ b/src/main/java/project/trendpick_pro/domain/delivery/service/DeliveryService.java @@ -1,18 +1,5 @@ package project.trendpick_pro.domain.delivery.service; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import project.trendpick_pro.domain.delivery.repository.DeliveryRepository; - -@Service -@RequiredArgsConstructor -public class DeliveryService { - - private final DeliveryRepository deliveryRepository; - - public void updateDeliveryStatus(Long deliveryId, String status) { -// deliveryRepository.updateDeliveryStatus(deliveryId, status); - } - - +public interface DeliveryService { + void updateDeliveryStatus(Long deliveryId, String status); } diff --git a/src/main/java/project/trendpick_pro/domain/delivery/service/DeliveryServiceImpl.java b/src/main/java/project/trendpick_pro/domain/delivery/service/DeliveryServiceImpl.java new file mode 100644 index 00000000..636ea5cd --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/delivery/service/DeliveryServiceImpl.java @@ -0,0 +1,15 @@ +package project.trendpick_pro.domain.delivery.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import project.trendpick_pro.domain.delivery.repository.DeliveryRepository; + +@Service +@RequiredArgsConstructor +public class DeliveryServiceImpl implements DeliveryService{ + private final DeliveryRepository deliveryRepository; + + public void updateDeliveryStatus(Long deliveryId, String status) { +// deliveryRepository.updateDeliveryStatus(deliveryId, status); + } +} From 6210a8c530f6276aa1f6efdcca2925884411c79b Mon Sep 17 00:00:00 2001 From: mmunkyeong Date: Mon, 10 Jul 2023 18:32:31 +0900 Subject: [PATCH 18/26] =?UTF-8?q?refactor:=20=EB=B8=8C=EB=9E=9C=EB=93=9C?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=EC=99=B8=20=EC=A0=91=EA=B7=BC=20?= =?UTF-8?q?=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81(#354)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/rebate/controller/AdmRebateController.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/project/trendpick_pro/domain/rebate/controller/AdmRebateController.java b/src/main/java/project/trendpick_pro/domain/rebate/controller/AdmRebateController.java index 5fc55309..4e0511c5 100644 --- a/src/main/java/project/trendpick_pro/domain/rebate/controller/AdmRebateController.java +++ b/src/main/java/project/trendpick_pro/domain/rebate/controller/AdmRebateController.java @@ -33,7 +33,8 @@ public class AdmRebateController { @GetMapping("/makeData") @PreAuthorize("hasAuthority({'BRAND_ADMIN'})") public String showMakeData() { - if(!rq.getRollMember().getRole().getValue().equals("BRAND_ADMIN")){ + Member member=rq.getRollMember(); + if(member.getRole().getValue().equals("BRAND_ADMIN")){ return rq.historyBack("브랜드 관리자만 접근할 수 있습니다."); } return "trendpick/admin/makeData"; @@ -53,7 +54,8 @@ public String makeData(String yearMonth) { @GetMapping("/rebateOrderItemList") @PreAuthorize("hasAuthority({'BRAND_ADMIN'})") public String showRebateOrderItemList(String yearMonth, Model model) { - if(!rq.getRollMember().getRole().getValue().equals("BRAND_ADMIN")){ + Member member=rq.getRollMember(); + if(member.getRole().getValue().equals("BRAND_ADMIN")){ return rq.historyBack("브랜드 관리자만 접근할 수 있습니다."); } @@ -73,7 +75,9 @@ public String showRebateOrderItemList(String yearMonth, Model model) { @PreAuthorize("hasAuthority({'BRAND_ADMIN'})") public String rebateOne(@PathVariable long orderItemId, HttpServletRequest req) { RsData rebateRsData = rebateService.rebate(orderItemId); - + if(rebateRsData.isFail()){ + return rq.historyBack("정산할 수 없는 상태입니다."); + } String referer = req.getHeader("Referer"); String yearMonth = Ut.url.getQueryParamValue(referer, "yearMonth", ""); From 95ca46785a12ae59dbfe4d89bae4388c0b64d89b Mon Sep 17 00:00:00 2001 From: mmunkyeong Date: Mon, 10 Jul 2023 18:44:37 +0900 Subject: [PATCH 19/26] =?UTF-8?q?fix:=20=EC=8A=A4=EB=A0=88=EB=93=9C=20?= =?UTF-8?q?=EA=B0=92=20=EB=B3=80=EA=B2=BD(#354)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../trendpick_pro/domain/orders/service/OrderServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/project/trendpick_pro/domain/orders/service/OrderServiceImpl.java b/src/main/java/project/trendpick_pro/domain/orders/service/OrderServiceImpl.java index 64512b92..c3f6497a 100644 --- a/src/main/java/project/trendpick_pro/domain/orders/service/OrderServiceImpl.java +++ b/src/main/java/project/trendpick_pro/domain/orders/service/OrderServiceImpl.java @@ -113,7 +113,7 @@ public RsData productToOrder(Member member, Long id, int quantity, String @KafkaListener(topicPattern = "orders", groupId = "group_id") public void orderToOrder(@Payload String Id) throws JsonProcessingException { try { - Thread.sleep(750); + Thread.sleep(800); } catch (InterruptedException e) { e.printStackTrace(); } From cb410694d4dcfabfdfdd488af896cccc377ec35c Mon Sep 17 00:00:00 2001 From: SoohoLee Date: Mon, 10 Jul 2023 22:53:45 +0900 Subject: [PATCH 20/26] =?UTF-8?q?refactor:=20=EC=BF=A0=ED=8F=B0=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81=20(#364)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/cash/entity/dto/CashResponse.java | 13 +++ .../controller/CouponCardController.java | 43 ++++----- .../coupon/controller/CouponController.java | 1 - .../domain/coupon/entity/Coupon.java | 9 +- .../domain/coupon/entity/CouponCard.java | 4 +- .../response/CouponCardByApplyResponse.java | 5 +- .../exception/CouponNotFoundException.java | 14 +++ .../coupon/service/CouponCardService.java | 79 ++-------------- .../domain/coupon/service/CouponService.java | 89 +------------------ .../service/impl/CouponCardServiceImpl.java | 85 ++++++++++++++++++ .../service/impl/CouponServiceImpl.java | 86 ++++++++++++++++++ .../OrderItemNotFoundException.java | 14 +++ 12 files changed, 251 insertions(+), 191 deletions(-) create mode 100644 src/main/java/project/trendpick_pro/domain/cash/entity/dto/CashResponse.java create mode 100644 src/main/java/project/trendpick_pro/domain/coupon/exception/CouponNotFoundException.java create mode 100644 src/main/java/project/trendpick_pro/domain/coupon/service/impl/CouponCardServiceImpl.java create mode 100644 src/main/java/project/trendpick_pro/domain/coupon/service/impl/CouponServiceImpl.java create mode 100644 src/main/java/project/trendpick_pro/domain/orders/exceoption/OrderItemNotFoundException.java diff --git a/src/main/java/project/trendpick_pro/domain/cash/entity/dto/CashResponse.java b/src/main/java/project/trendpick_pro/domain/cash/entity/dto/CashResponse.java new file mode 100644 index 00000000..7eed5f23 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/cash/entity/dto/CashResponse.java @@ -0,0 +1,13 @@ +package project.trendpick_pro.domain.cash.entity.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import project.trendpick_pro.domain.cash.entity.CashLog; + +@Getter +@AllArgsConstructor +public class CashResponse { + + CashLog cashLog; + long newRestCash; +} diff --git a/src/main/java/project/trendpick_pro/domain/coupon/controller/CouponCardController.java b/src/main/java/project/trendpick_pro/domain/coupon/controller/CouponCardController.java index ce99cdd4..2a9e203e 100644 --- a/src/main/java/project/trendpick_pro/domain/coupon/controller/CouponCardController.java +++ b/src/main/java/project/trendpick_pro/domain/coupon/controller/CouponCardController.java @@ -2,14 +2,12 @@ import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import project.trendpick_pro.domain.common.base.rq.Rq; -import project.trendpick_pro.domain.coupon.entity.CouponCard; import project.trendpick_pro.domain.coupon.entity.dto.response.CouponCardByApplyResponse; import project.trendpick_pro.domain.coupon.service.CouponCardService; -import project.trendpick_pro.domain.orders.service.OrderService; import project.trendpick_pro.global.rsData.RsData; import java.util.List; @@ -18,43 +16,40 @@ @RequiredArgsConstructor @RequestMapping("/trendpick/usr/couponCards") public class CouponCardController { + private final Rq rq; private final CouponCardService couponCardService; + @PreAuthorize("hasRole('MEMBER')") @PostMapping("/{couponId}/issue") - public String issue(@PathVariable("couponId") Long couponId, HttpServletRequest req) { - RsData result = couponCardService.issue(rq.getMember(), couponId); - String referer = req.getHeader("referer"); - if (result.isFail()) - return rq.historyBack(result); - return rq.redirectWithMsg(referer, result); + public String issueCoupon(@PathVariable("couponId") Long couponId, HttpServletRequest req) { + return processRequest(couponCardService.issue(rq.getMember(), couponId), "쿠폰이 발급되었습니다.", req); } + @PreAuthorize("hasRole('MEMBER')") @GetMapping("apply") @ResponseBody - public List apply(@RequestParam("orderItem") Long orderItemId, Model model) { -// model.addAttribute("couponCards", couponCardService.showCouponCardsByOrderItem(orderItemId)); -// model.addAttribute("orderItemId", orderItemId); -// return "trendpick/coupons/couponcards"; + public List showApplicableCoupons(@RequestParam("orderItem") Long orderItemId) { return couponCardService.showCouponCardsByOrderItem(orderItemId); } + @PreAuthorize("hasRole('MEMBER')") @PostMapping("apply") - public String apply(@RequestParam("couponCard") Long couponCardId, @RequestParam("orderItem") Long orderItemId, HttpServletRequest req) { - RsData result = couponCardService.apply(couponCardId, orderItemId); - if (result.isFail()) - return rq.historyBack(result); - - String referer = req.getHeader("referer"); - return rq.redirectWithMsg(referer, "쿠폰이 적용되었습니다."); + public String applyCoupon(@RequestParam("couponCard") Long couponCardId, @RequestParam("orderItem") Long orderItemId, HttpServletRequest req) { + return processRequest(couponCardService.apply(couponCardId, orderItemId), "쿠폰이 적용되었습니다.", req); } + @PreAuthorize("hasRole('MEMBER')") @PostMapping("cancel") - public String cancel(@RequestParam("orderItem") Long orderItemId, HttpServletRequest req) { - RsData result = couponCardService.cancel(orderItemId); - if(result.isFail()) + public String cancelCoupon(@RequestParam("orderItem") Long orderItemId, HttpServletRequest req) { + return processRequest(couponCardService.cancel(orderItemId), "쿠폰 적용이 취소되었습니다.", req); + } + + private String processRequest(RsData result, String successMsg, HttpServletRequest req) { + if(result.isFail()) { return rq.historyBack(result); + } String referer = req.getHeader("referer"); - return rq.redirectWithMsg(referer, result); + return rq.redirectWithMsg(referer, successMsg); } } diff --git a/src/main/java/project/trendpick_pro/domain/coupon/controller/CouponController.java b/src/main/java/project/trendpick_pro/domain/coupon/controller/CouponController.java index f572a4e0..a578a56d 100644 --- a/src/main/java/project/trendpick_pro/domain/coupon/controller/CouponController.java +++ b/src/main/java/project/trendpick_pro/domain/coupon/controller/CouponController.java @@ -8,7 +8,6 @@ import project.trendpick_pro.domain.common.base.rq.Rq; import project.trendpick_pro.domain.coupon.entity.dto.request.StoreCouponSaveRequest; import project.trendpick_pro.domain.coupon.service.CouponService; -import project.trendpick_pro.domain.member.entity.Member; import project.trendpick_pro.global.rsData.RsData; import java.io.UnsupportedEncodingException; diff --git a/src/main/java/project/trendpick_pro/domain/coupon/entity/Coupon.java b/src/main/java/project/trendpick_pro/domain/coupon/entity/Coupon.java index 0d6966cb..761f0d22 100644 --- a/src/main/java/project/trendpick_pro/domain/coupon/entity/Coupon.java +++ b/src/main/java/project/trendpick_pro/domain/coupon/entity/Coupon.java @@ -24,12 +24,15 @@ public class Coupon extends BaseTimeEntity { @Column(name = "name", nullable = false) private String name; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "store_id", nullable = false) private Store store; + @Embedded @Column(nullable = false) - private ExpirationPeriod expirationPeriod; //쿠폰 유효기한 + private ExpirationPeriod expirationPeriod; + @Column(name = "limit_count") private int limitCount; @Column(name = "issue_count") @@ -93,4 +96,8 @@ public boolean validateMinimumPurchaseAmount(int price){ public void increaseIssueCount(){ this.issueCount = getIssueCount() + 1; } + + public void decreaseIssueCount(){ + this.issueCount -= - 1; + } } diff --git a/src/main/java/project/trendpick_pro/domain/coupon/entity/CouponCard.java b/src/main/java/project/trendpick_pro/domain/coupon/entity/CouponCard.java index df7961f5..fdf4ed19 100644 --- a/src/main/java/project/trendpick_pro/domain/coupon/entity/CouponCard.java +++ b/src/main/java/project/trendpick_pro/domain/coupon/entity/CouponCard.java @@ -4,7 +4,6 @@ import lombok.AccessLevel; import lombok.Getter; import lombok.NoArgsConstructor; -import org.springframework.lang.Nullable; import project.trendpick_pro.domain.common.base.BaseTimeEntity; import project.trendpick_pro.domain.coupon.entity.expirationPeriod.ExpirationPeriod; import project.trendpick_pro.domain.member.entity.Member; @@ -50,6 +49,7 @@ private CouponCard(Coupon coupon, Member member){ this.member = member; this.expirationPeriod = coupon.getExpirationPeriod().CopyExpirationPeriod(); //시작날짜 마감날짜만 가져옴 this.couponCode = UUID.randomUUID(); + coupon.decreaseIssueCount(); if(LocalDateTime.now().isBefore(this.expirationPeriod.getStartDate())) this.status = CouponStatus.NOT_YET_ACTIVE; @@ -96,6 +96,6 @@ public void cancel(OrderItem orderItem){ this.status = CouponStatus.AVAILABLE; this.usedDate = null; orderItem.cancelCouponCard(); + coupon.increaseIssueCount(); } - } diff --git a/src/main/java/project/trendpick_pro/domain/coupon/entity/dto/response/CouponCardByApplyResponse.java b/src/main/java/project/trendpick_pro/domain/coupon/entity/dto/response/CouponCardByApplyResponse.java index a6d08f32..3af66237 100644 --- a/src/main/java/project/trendpick_pro/domain/coupon/entity/dto/response/CouponCardByApplyResponse.java +++ b/src/main/java/project/trendpick_pro/domain/coupon/entity/dto/response/CouponCardByApplyResponse.java @@ -4,7 +4,6 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; -import project.trendpick_pro.domain.coupon.entity.Coupon; import project.trendpick_pro.domain.coupon.entity.CouponCard; import project.trendpick_pro.domain.orders.entity.OrderItem; @@ -30,13 +29,11 @@ public static CouponCardByApplyResponse of(CouponCard couponCard, OrderItem orde couponCard.getCoupon().getName(), couponCard.getExpirationPeriod().getStartDate(), couponCard.getExpirationPeriod().getEndDate(), - orderItem.getOrderPrice() * couponCard.getCoupon().getDiscountPercent() / 100) - ; + orderItem.getOrderPrice() * couponCard.getCoupon().getDiscountPercent() / 100); } public String getFormattedDiscountPrice() { NumberFormat numberFormat = NumberFormat.getInstance(Locale.getDefault()); return numberFormat.format(getDiscountPrice())+"원"; } - } diff --git a/src/main/java/project/trendpick_pro/domain/coupon/exception/CouponNotFoundException.java b/src/main/java/project/trendpick_pro/domain/coupon/exception/CouponNotFoundException.java new file mode 100644 index 00000000..34dcf379 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/coupon/exception/CouponNotFoundException.java @@ -0,0 +1,14 @@ +package project.trendpick_pro.domain.coupon.exception; + +import org.springframework.http.HttpStatus; +import project.trendpick_pro.global.exception.BaseException; +import project.trendpick_pro.global.exception.ErrorCode; + +public class CouponNotFoundException extends BaseException { + + private static final ErrorCode code = ErrorCode.COUPON_NOT_FOUND; + + public CouponNotFoundException(String message) { + super(code, HttpStatus.BAD_REQUEST, message); + } +} diff --git a/src/main/java/project/trendpick_pro/domain/coupon/service/CouponCardService.java b/src/main/java/project/trendpick_pro/domain/coupon/service/CouponCardService.java index 6d869ed9..07a2cd3a 100644 --- a/src/main/java/project/trendpick_pro/domain/coupon/service/CouponCardService.java +++ b/src/main/java/project/trendpick_pro/domain/coupon/service/CouponCardService.java @@ -1,89 +1,20 @@ package project.trendpick_pro.domain.coupon.service; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import project.trendpick_pro.domain.coupon.entity.Coupon; import project.trendpick_pro.domain.coupon.entity.CouponCard; import project.trendpick_pro.domain.coupon.entity.dto.response.CouponCardByApplyResponse; -import project.trendpick_pro.domain.coupon.repository.CouponCardRepository; -import project.trendpick_pro.domain.coupon.repository.CouponRepository; import project.trendpick_pro.domain.member.entity.Member; -import project.trendpick_pro.domain.orders.entity.OrderItem; -import project.trendpick_pro.domain.orders.repository.OrderItemRepository; import project.trendpick_pro.global.rsData.RsData; -import java.util.ArrayList; import java.util.List; -import java.util.Optional; -@Service -@Transactional(readOnly = true) -@RequiredArgsConstructor -public class CouponCardService { - private final CouponCardRepository couponCardRepository; - private final CouponRepository couponRepository; - private final OrderItemRepository orderItemRepository; +public interface CouponCardService { - @Transactional - public RsData issue(Member member, Long couponId) { - Coupon coupon = couponRepository.findById(couponId).orElseThrow( - () -> new IllegalArgumentException("존재하지 않는 쿠폰입니다.") - ); + RsData issue(Member member, Long couponId); - int count = couponCardRepository.countByCouponIdAndMemberId(couponId, member.getId()); - if(count > 0) - return RsData.of("F-3", "이미 발급 받으신 쿠폰입니다."); + List showCouponCardsByOrderItem(Long orderItemId); - if(!coupon.validateLimitCount()) - return RsData.of("F-1", "수량이 모두 소진되었습니다."); - if(!coupon.validateLimitIssueDate()) - return RsData.of("F-2", "쿠폰 발급 가능 날짜가 지났습니다."); + RsData apply(Long couponCardId, Long orderItemId); - CouponCard savedCouponCard = couponCardRepository.save(CouponCard.of(coupon, member)); - return RsData.of("S-1", "%s 쿠폰이 발급되었습니다.".formatted(coupon.getName()), savedCouponCard); - } + RsData cancel(Long orderItemId); - public List showCouponCardsByOrderItem(Long orderItemId) { - OrderItem orderItem = orderItemRepository.findById(orderItemId).orElseThrow( - () -> new IllegalArgumentException("해당 주문상품은 존재하지 않습니다.") - ); - - List couponCardList = couponCardRepository.findAllByBrand(orderItem.getProduct().getBrand().getName()); - List responses = new ArrayList<>(); - for (CouponCard couponCard : couponCardList) { - if (couponCard.validate(orderItem)) - responses.add(CouponCardByApplyResponse.of(couponCard, orderItem)); - } - return responses; - } - - @Transactional - public RsData apply(Long couponCardId, Long orderItemId) { - OrderItem orderItem = orderItemRepository.findById(orderItemId).orElseThrow( - () -> new IllegalArgumentException("해당 주문상품은 존재하지 않습니다.") - ); - - CouponCard couponCard = couponCardRepository.findById(couponCardId).orElse(null); - if(couponCard == null) - return RsData.of("F-1", "존재하지 않는 쿠폰입니다."); - if (!couponCard.validate(orderItem)) - return RsData.of("F-2", "해당 주문상품에는 사용하실 수 없는 쿠폰입니다."); - - couponCard.use(orderItem); - return RsData.of("S-1", "쿠폰이 적용되었습니다."); - } - - @Transactional - public RsData cancel(Long orderItemId) { - OrderItem orderItem = orderItemRepository.findById(orderItemId).orElseThrow( - () -> new IllegalArgumentException("해당 주문상품은 존재하지 않습니다.") - ); - CouponCard couponCard = orderItem.getCouponCard(); - if(couponCard == null) - return RsData.of("F-1", "해당 주문상품에 적용된 쿠폰이 없습니다."); - - couponCard.cancel(orderItem); - return RsData.of("S-1", "쿠폰이 취소되었습니다."); - } } diff --git a/src/main/java/project/trendpick_pro/domain/coupon/service/CouponService.java b/src/main/java/project/trendpick_pro/domain/coupon/service/CouponService.java index abc334e4..a18133ed 100644 --- a/src/main/java/project/trendpick_pro/domain/coupon/service/CouponService.java +++ b/src/main/java/project/trendpick_pro/domain/coupon/service/CouponService.java @@ -1,94 +1,13 @@ package project.trendpick_pro.domain.coupon.service; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import project.trendpick_pro.domain.coupon.entity.Coupon; import project.trendpick_pro.domain.coupon.entity.dto.request.StoreCouponSaveRequest; import project.trendpick_pro.domain.coupon.entity.dto.response.SimpleCouponResponse; -import project.trendpick_pro.domain.coupon.entity.expirationPeriod.ExpirationType; -import project.trendpick_pro.domain.coupon.repository.CouponRepository; -import project.trendpick_pro.domain.product.entity.product.Product; -import project.trendpick_pro.domain.product.service.ProductService; -import project.trendpick_pro.domain.store.service.StoreService; import project.trendpick_pro.global.rsData.RsData; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.util.ArrayList; import java.util.List; -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class CouponService { - private final CouponRepository couponRepository; - private final StoreService storeService; - private final ProductService productService; - - @Transactional - public RsData generate(String storeName, StoreCouponSaveRequest storeCouponSaveRequest) { - RsData validateExpirationPeriodResult = validateExpirationPeriod(storeCouponSaveRequest); - if (validateExpirationPeriodResult.isFail()) - return validateExpirationPeriodResult; - - Coupon coupon = - Coupon.generate(storeService.findByBrand(storeName), storeCouponSaveRequest); - couponRepository.save(coupon); - return RsData.of("S-1", "쿠폰이 성공적으로 발급되었습니다."); - } - - private static RsData validateExpirationPeriod(StoreCouponSaveRequest storeCouponSaveRequest) { - if (storeCouponSaveRequest.getExpirationType().equals(ExpirationType.ISSUE_AFTER_DATE.getValue())) { - if (storeCouponSaveRequest.getIssueAfterDate() == null) - return RsData.of("F-4", "발급된 이후의 유효기간을 설정하셔야 합니다."); - - return RsData.of("S-2", "유효기간 검증 성공"); - } - - //PERIOD 타입이라면 null로 들어온 값이 없어야 한다. - if (storeCouponSaveRequest.getStartDate() == null || storeCouponSaveRequest.getEndDate() == null) - return RsData.of("F-3", "날짜 직접선택 타입은 시작날짜와 마감날짜를 모두 선택하셔야 합니다."); - - if (storeCouponSaveRequest.getStartDate().isBefore(LocalDateTime.now().plusDays(1).with(LocalTime.MIDNIGHT))) - return RsData.of("F-1", "쿠폰 발급 시작일은 다음날 00시 00분부터 가능합니다."); - - if (storeCouponSaveRequest.getEndDate().isBefore(storeCouponSaveRequest.getStartDate().plusDays(1))) - return RsData.of("F-2", "마감 기한은 발급 날짜보다 하루 이상 이후여야 합니다."); - - return RsData.of("S-1", "검증성공"); - } - - public List findAllCoupons() { - List coupons = couponRepository.findAll(); - - List responses = new ArrayList<>(); - for (Coupon coupon : coupons) - responses.add(SimpleCouponResponse.of(coupon)); - - return responses; - } - - public List findCouponsByProduct(Long productId) { - Product product = productService.findByIdWithBrand(productId); - - List coupons = filteredCoupons(couponRepository.findAllByBrand(product.getBrand().getName()), product); - List responses = new ArrayList<>(); - for(Coupon coupon : coupons) - responses.add(SimpleCouponResponse.of(coupon)); - - return responses; - } - - private List filteredCoupons(List coupons, Product product) { - List filteredCoupons = new ArrayList<>(); - - //추후에 쿠폰 사용 조건이 생기면 추가 //Validation을 만드는 것도 고려해봐야 할듯 - for (Coupon coupon : coupons) { - if(coupon.validateMinimumPurchaseAmount(product.getProductOption().getPrice()) && coupon.validateLimitCount() && coupon.validateLimitIssueDate()) - filteredCoupons.add(coupon); - } - return filteredCoupons; - } - +public interface CouponService { + RsData generate(String storeName, StoreCouponSaveRequest storeCouponSaveRequest); + List findAllCoupons(); + List findCouponsByProduct(Long productId); } diff --git a/src/main/java/project/trendpick_pro/domain/coupon/service/impl/CouponCardServiceImpl.java b/src/main/java/project/trendpick_pro/domain/coupon/service/impl/CouponCardServiceImpl.java new file mode 100644 index 00000000..45b442aa --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/coupon/service/impl/CouponCardServiceImpl.java @@ -0,0 +1,85 @@ +package project.trendpick_pro.domain.coupon.service.impl; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.coupon.entity.Coupon; +import project.trendpick_pro.domain.coupon.entity.CouponCard; +import project.trendpick_pro.domain.coupon.entity.dto.response.CouponCardByApplyResponse; +import project.trendpick_pro.domain.coupon.exception.CouponNotFoundException; +import project.trendpick_pro.domain.coupon.repository.CouponCardRepository; +import project.trendpick_pro.domain.coupon.repository.CouponRepository; +import project.trendpick_pro.domain.coupon.service.CouponCardService; +import project.trendpick_pro.domain.member.entity.Member; +import project.trendpick_pro.domain.orders.entity.OrderItem; +import project.trendpick_pro.domain.orders.exceoption.OrderItemNotFoundException; +import project.trendpick_pro.domain.orders.repository.OrderItemRepository; +import project.trendpick_pro.global.rsData.RsData; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class CouponCardServiceImpl implements CouponCardService { + + private final CouponCardRepository couponCardRepository; + private final CouponRepository couponRepository; + private final OrderItemRepository orderItemRepository; + + @Transactional + @Override + public RsData issue(Member member, Long couponId) { + Coupon coupon = couponRepository.findById(couponId).orElseThrow( + () -> new CouponNotFoundException("존재하지 않는 쿠폰입니다.")); + int count = couponCardRepository.countByCouponIdAndMemberId(couponId, member.getId()); + if(count > 0) + return RsData.of("F-3", "이미 발급 받으신 쿠폰입니다."); + if(!coupon.validateLimitCount()) + return RsData.of("F-1", "수량이 모두 소진되었습니다."); + if(!coupon.validateLimitIssueDate()) + return RsData.of("F-2", "쿠폰 발급 가능 날짜가 지났습니다."); + + CouponCard savedCouponCard = couponCardRepository.save(CouponCard.of(coupon, member)); + return RsData.of("S-1", coupon.getName() + " 쿠폰이 발급되었습니다.", savedCouponCard); + } + + @Transactional(readOnly = true) + @Override + public List showCouponCardsByOrderItem(Long orderItemId) { + OrderItem orderItem = orderItemRepository.findById(orderItemId).orElseThrow( + () -> new OrderItemNotFoundException("주문되지 않은 상품입니다.")); + List couponCards = couponCardRepository.findAllByBrand(orderItem.getProduct().getBrand().getName()); + return createCouponCardByApplyResponseList(couponCards, orderItem); + } + + @Transactional + @Override + public RsData apply(Long couponCardId, Long orderItemId) { + OrderItem orderItem = orderItemRepository.findById(orderItemId).orElseThrow( + () -> new OrderItemNotFoundException("주문되지 않은 상품입니다.")); + CouponCard couponCard = couponCardRepository.findById(couponCardId).orElseThrow( + () -> new CouponNotFoundException("존재하지 않은 쿠폰입니다.")); + if (!couponCard.validate(orderItem)) + return RsData.of("F-1", "해당 주문상품에 적용된 쿠폰이 없습니다."); + couponCard.use(orderItem); + return RsData.of("S-1", "쿠폰이 적용되었습니다."); + } + + @Transactional + @Override + public RsData cancel(Long orderItemId) { + OrderItem orderItem = orderItemRepository.findById(orderItemId).orElseThrow( + () -> new OrderItemNotFoundException("주문되지 않은 상품입니다.")); + CouponCard couponCard = orderItem.getCouponCard(); + couponCard.cancel(orderItem); + return RsData.of("S-1", "쿠폰이 취소되었습니다."); + } + + private List createCouponCardByApplyResponseList(List couponCards, OrderItem orderItem) { + return couponCards.stream() + .filter(couponCard -> couponCard.validate(orderItem)) + .map(couponCard -> CouponCardByApplyResponse.of(couponCard, orderItem)) + .toList(); + } +} + diff --git a/src/main/java/project/trendpick_pro/domain/coupon/service/impl/CouponServiceImpl.java b/src/main/java/project/trendpick_pro/domain/coupon/service/impl/CouponServiceImpl.java new file mode 100644 index 00000000..1b5097a4 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/coupon/service/impl/CouponServiceImpl.java @@ -0,0 +1,86 @@ +package project.trendpick_pro.domain.coupon.service.impl; + +import project.trendpick_pro.domain.coupon.service.CouponService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.coupon.entity.Coupon; +import project.trendpick_pro.domain.coupon.entity.dto.request.StoreCouponSaveRequest; +import project.trendpick_pro.domain.coupon.entity.dto.response.SimpleCouponResponse; +import project.trendpick_pro.domain.coupon.entity.expirationPeriod.ExpirationType; +import project.trendpick_pro.domain.coupon.repository.CouponRepository; +import project.trendpick_pro.domain.product.entity.product.Product; +import project.trendpick_pro.domain.product.service.ProductService; +import project.trendpick_pro.domain.store.service.StoreService; +import project.trendpick_pro.global.rsData.RsData; + +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.List; + + +@Service +@RequiredArgsConstructor +public class CouponServiceImpl implements CouponService { + + private final CouponRepository couponRepository; + private final StoreService storeService; + private final ProductService productService; + + @Override + @Transactional + public RsData generate(String storeName, StoreCouponSaveRequest storeCouponSaveRequest) { + RsData validateExpirationPeriodResult = validateExpirationPeriod(storeCouponSaveRequest); + if (validateExpirationPeriodResult.isFail()) + return validateExpirationPeriodResult; + + Coupon coupon = Coupon.generate(storeService.findByBrand(storeName), storeCouponSaveRequest); + couponRepository.save(coupon); + return RsData.of("S-1", "쿠폰이 성공적으로 발급되었습니다."); + } + + @Override + @Transactional(readOnly = true) + public List findAllCoupons() { + return convertCouponsToResponses(couponRepository.findAll()); + } + + @Override + @Transactional(readOnly = true) + public List findCouponsByProduct(Long productId) { + Product product = productService.findByIdWithBrand(productId); + List coupons = filteredCoupons(couponRepository.findAllByBrand(product.getBrand().getName()), product); + return convertCouponsToResponses(coupons); + } + + private List convertCouponsToResponses(List coupons) { + return coupons.stream() + .map(SimpleCouponResponse::of) + .toList(); + } + + private List filteredCoupons(List coupons, Product product) { + return coupons.stream() + .filter(coupon -> coupon.validateMinimumPurchaseAmount(product.getProductOption().getPrice()) + && coupon.validateLimitCount() + && coupon.validateLimitIssueDate()) + .toList(); + } + + private static RsData validateExpirationPeriod(StoreCouponSaveRequest storeCouponSaveRequest) { + if (storeCouponSaveRequest.getExpirationType().equals(ExpirationType.ISSUE_AFTER_DATE.getValue())) { + if (storeCouponSaveRequest.getIssueAfterDate() == null) + return RsData.of("F-4", "발급된 이후의 유효기간을 설정하셔야 합니다."); + return RsData.of("S-2", "유효기간 검증 성공"); + } + + if (storeCouponSaveRequest.getStartDate() == null || storeCouponSaveRequest.getEndDate() == null) + return RsData.of("F-3", "날짜 직접선택 타입은 시작날짜와 마감날짜를 모두 선택하셔야 합니다."); + if (storeCouponSaveRequest.getStartDate().isBefore(LocalDateTime.now().plusDays(1).with(LocalTime.MIDNIGHT))) + return RsData.of("F-1", "쿠폰 발급 시작일은 다음날 00시 00분부터 가능합니다."); + if (storeCouponSaveRequest.getEndDate().isBefore(storeCouponSaveRequest.getStartDate().plusDays(1))) + return RsData.of("F-2", "마감 기한은 발급 날짜보다 하루 이상 이후여야 합니다."); + + return RsData.of("S-1", "검증성공"); + } +} \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/domain/orders/exceoption/OrderItemNotFoundException.java b/src/main/java/project/trendpick_pro/domain/orders/exceoption/OrderItemNotFoundException.java new file mode 100644 index 00000000..d8c758d9 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/orders/exceoption/OrderItemNotFoundException.java @@ -0,0 +1,14 @@ +package project.trendpick_pro.domain.orders.exceoption; + +import org.springframework.http.HttpStatus; +import project.trendpick_pro.global.exception.BaseException; +import project.trendpick_pro.global.exception.ErrorCode; + +public class OrderItemNotFoundException extends BaseException { + + private static final ErrorCode code = ErrorCode.ORDERITEM_NOT_FOUND; + + public OrderItemNotFoundException(String message) { + super(code, HttpStatus.BAD_REQUEST, message); + } +} From ed652dbce79b29c95e549da82a621455ba4e77bb Mon Sep 17 00:00:00 2001 From: SoohoLee Date: Mon, 10 Jul 2023 22:54:54 +0900 Subject: [PATCH 21/26] =?UTF-8?q?refactor:=20=EB=AC=B8=EC=9D=98=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81=20(#364)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/ask/controller/AskController.java | 31 ++++---- .../trendpick_pro/domain/ask/entity/Ask.java | 7 +- .../domain/ask/entity/dto/form/AskForm.java | 8 +- .../dto/request/AskByProductRequest.java | 12 --- .../ask/entity/dto/request/AskRequest.java | 18 ----- .../ask/entity/dto/response/AskResponse.java | 2 +- .../ask/exception/AskNotFoundException.java | 14 ++++ .../ask/exception/AskNotMatchException.java | 14 ++++ .../domain/ask/repository/AskRepository.java | 7 -- .../ask/repository/AskRepositoryCustom.java | 3 - .../domain/ask/service/AskService.java | 79 ++----------------- .../ask/service/impl/AskServiceImpl.java | 77 ++++++++++++++++++ 12 files changed, 135 insertions(+), 137 deletions(-) delete mode 100644 src/main/java/project/trendpick_pro/domain/ask/entity/dto/request/AskByProductRequest.java delete mode 100644 src/main/java/project/trendpick_pro/domain/ask/entity/dto/request/AskRequest.java create mode 100644 src/main/java/project/trendpick_pro/domain/ask/exception/AskNotFoundException.java create mode 100644 src/main/java/project/trendpick_pro/domain/ask/exception/AskNotMatchException.java create mode 100644 src/main/java/project/trendpick_pro/domain/ask/service/impl/AskServiceImpl.java diff --git a/src/main/java/project/trendpick_pro/domain/ask/controller/AskController.java b/src/main/java/project/trendpick_pro/domain/ask/controller/AskController.java index 4111973d..bd36c6f1 100644 --- a/src/main/java/project/trendpick_pro/domain/ask/controller/AskController.java +++ b/src/main/java/project/trendpick_pro/domain/ask/controller/AskController.java @@ -22,9 +22,10 @@ public class AskController { private final AskService askService; private final AnswerService answerService; + private final Rq rq; - @PreAuthorize("isAuthenticated()") + @PreAuthorize("hasAuthority('MEMBER')") @GetMapping("/register") public String registerForm(@RequestParam("product") Long productId, AskForm askForm, Model model) { askForm.setProductId(productId); @@ -32,18 +33,19 @@ public String registerForm(@RequestParam("product") Long productId, AskForm askF return "trendpick/customerservice/asks/register"; } - @PreAuthorize("isAuthenticated()") + @PreAuthorize("hasAuthority('MEMBER')") @PostMapping("/register") public String registerAsk(@Valid AskForm askForm) { RsData result = askService.register(rq.getMember(), askForm); - if(result.isFail()) - return rq.redirectWithMsg("/trendpick/products/%s".formatted(askForm.getProductId()), result); - + if(result.isFail()) { + return rq.historyBack(result); + } return rq.redirectWithMsg("/trendpick/products/%s".formatted(askForm.getProductId()), result); } + @PreAuthorize("permitAll()") @GetMapping("/{askId}") - public String showAsk(@PathVariable Long askId, AnswerForm answerForm, Model model) { + public String showAsk(@PathVariable Long askId, Model model) { model.addAttribute("ask", askService.show(askId)); model.addAttribute("answers", answerService.showAll(askId)); model.addAttribute("answerForm", new AnswerForm()); @@ -54,31 +56,30 @@ public String showAsk(@PathVariable Long askId, AnswerForm answerForm, Model mod @PostMapping("/delete/{askId}") public String deleteAsk(@PathVariable Long askId) { RsData result = askService.delete(rq.getMember(), askId); - if(result.isFail()) + if(result.isFail()) { return rq.historyBack(result); - + } return rq.redirectWithMsg("/trendpick/products/%s".formatted(result.getData()), result); } - @PreAuthorize("isAuthenticated()") + @PreAuthorize("hasAuthority('MEMBER')") @GetMapping("/edit/{askId}") public String modifyForm(@PathVariable Long askId, Model model) { AskResponse ask = askService.show(askId); - if(!Objects.equals(ask.getMemberId(), rq.getMember().getId())) + if(!Objects.equals(ask.getMemberId(), rq.getMember().getId())) { return rq.historyBack("자신이 올린 문의글에 대해서만 수정 권한이 있습니다."); - + } model.addAttribute("askForm", new AskForm(ask.getAskId(), ask.getTitle(), ask.getContent())); - return "trendpick/customerservice/asks/register"; } - @PreAuthorize("isAuthenticated()") + @PreAuthorize("hasAuthority('MEMBER')") @PostMapping("/edit/{askId}") public String modifyAsk(@PathVariable Long askId, @Valid AskForm askForm) { RsData result = askService.modify(rq.getMember(), askId, askForm); - if (result.isFail()) + if (result.isFail()) { return rq.redirectWithMsg("/trendpick/customerservice/asks/%s".formatted(askId), result); - + } return rq.redirectWithMsg("/trendpick/customerservice/asks/%s".formatted(askId), "문의글 수정이 완료되었습니다."); } diff --git a/src/main/java/project/trendpick_pro/domain/ask/entity/Ask.java b/src/main/java/project/trendpick_pro/domain/ask/entity/Ask.java index 06a15d22..e165b6f3 100644 --- a/src/main/java/project/trendpick_pro/domain/ask/entity/Ask.java +++ b/src/main/java/project/trendpick_pro/domain/ask/entity/Ask.java @@ -10,6 +10,7 @@ import project.trendpick_pro.domain.common.base.BaseTimeEntity; import project.trendpick_pro.domain.member.entity.Member; import project.trendpick_pro.domain.product.entity.product.Product; + import java.util.ArrayList; import java.util.List; @@ -33,7 +34,10 @@ public class Ask extends BaseTimeEntity { @JoinColumn(name = "product_id") private Product product; + @Column(nullable = false) private String title; + + @Column(nullable = false) private String content; @Enumerated(EnumType.STRING) @@ -50,8 +54,7 @@ public static Ask of(Member member, Product product, AskForm askForm) { .title(askForm.getTitle()) .content(askForm.getContent()) .status(AskStatus.YET) - .build() - ; + .build(); } public void update(AskForm askForm) { diff --git a/src/main/java/project/trendpick_pro/domain/ask/entity/dto/form/AskForm.java b/src/main/java/project/trendpick_pro/domain/ask/entity/dto/form/AskForm.java index 7dfd8b87..43a4930f 100644 --- a/src/main/java/project/trendpick_pro/domain/ask/entity/dto/form/AskForm.java +++ b/src/main/java/project/trendpick_pro/domain/ask/entity/dto/form/AskForm.java @@ -2,21 +2,17 @@ import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; -import lombok.Getter; +import lombok.Data; import lombok.NoArgsConstructor; -import lombok.Setter; -@Getter -@Setter +@Data @AllArgsConstructor @NoArgsConstructor public class AskForm { private Long productId; - @NotBlank private String title; - @NotBlank private String content; } \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/domain/ask/entity/dto/request/AskByProductRequest.java b/src/main/java/project/trendpick_pro/domain/ask/entity/dto/request/AskByProductRequest.java deleted file mode 100644 index 0621a09c..00000000 --- a/src/main/java/project/trendpick_pro/domain/ask/entity/dto/request/AskByProductRequest.java +++ /dev/null @@ -1,12 +0,0 @@ -package project.trendpick_pro.domain.ask.entity.dto.request; - -import lombok.Getter; - -@Getter -public class AskByProductRequest { - private Long productId; - - public AskByProductRequest(Long productId) { - this.productId = productId; - } -} diff --git a/src/main/java/project/trendpick_pro/domain/ask/entity/dto/request/AskRequest.java b/src/main/java/project/trendpick_pro/domain/ask/entity/dto/request/AskRequest.java deleted file mode 100644 index ad30c873..00000000 --- a/src/main/java/project/trendpick_pro/domain/ask/entity/dto/request/AskRequest.java +++ /dev/null @@ -1,18 +0,0 @@ -package project.trendpick_pro.domain.ask.entity.dto.request; - - -import jakarta.validation.constraints.NotBlank; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Getter -@Setter -public class AskRequest { - - @NotBlank - private String title; - - @NotBlank - private String content; -} diff --git a/src/main/java/project/trendpick_pro/domain/ask/entity/dto/response/AskResponse.java b/src/main/java/project/trendpick_pro/domain/ask/entity/dto/response/AskResponse.java index 5609614d..7bc934bb 100644 --- a/src/main/java/project/trendpick_pro/domain/ask/entity/dto/response/AskResponse.java +++ b/src/main/java/project/trendpick_pro/domain/ask/entity/dto/response/AskResponse.java @@ -21,8 +21,8 @@ public class AskResponse { private String status; private LocalDateTime createdDate; - @QueryProjection @Builder + @QueryProjection public AskResponse(Long askId, Long productId, String productName, String memberName, Long memberId, String title,String content, String status, LocalDateTime createdDate) { this.askId = askId; this.productId = productId; diff --git a/src/main/java/project/trendpick_pro/domain/ask/exception/AskNotFoundException.java b/src/main/java/project/trendpick_pro/domain/ask/exception/AskNotFoundException.java new file mode 100644 index 00000000..71828f22 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/ask/exception/AskNotFoundException.java @@ -0,0 +1,14 @@ +package project.trendpick_pro.domain.ask.exception; + +import org.springframework.http.HttpStatus; +import project.trendpick_pro.global.exception.BaseException; +import project.trendpick_pro.global.exception.ErrorCode; + +public class AskNotFoundException extends BaseException { + + private static final ErrorCode code = ErrorCode.ASK_NOT_FOUND; + + public AskNotFoundException(String message) { + super(code, HttpStatus.BAD_REQUEST, message); + } +} diff --git a/src/main/java/project/trendpick_pro/domain/ask/exception/AskNotMatchException.java b/src/main/java/project/trendpick_pro/domain/ask/exception/AskNotMatchException.java new file mode 100644 index 00000000..7ad0f97c --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/ask/exception/AskNotMatchException.java @@ -0,0 +1,14 @@ +package project.trendpick_pro.domain.ask.exception; + +import org.springframework.http.HttpStatus; +import project.trendpick_pro.global.exception.BaseException; +import project.trendpick_pro.global.exception.ErrorCode; + +public class AskNotMatchException extends BaseException { + + private static final ErrorCode code = ErrorCode.ASK_NOT_MATCH; + + public AskNotMatchException(String message) { + super(code, HttpStatus.BAD_REQUEST, message); + } +} diff --git a/src/main/java/project/trendpick_pro/domain/ask/repository/AskRepository.java b/src/main/java/project/trendpick_pro/domain/ask/repository/AskRepository.java index a45c69c8..da9f284f 100644 --- a/src/main/java/project/trendpick_pro/domain/ask/repository/AskRepository.java +++ b/src/main/java/project/trendpick_pro/domain/ask/repository/AskRepository.java @@ -1,14 +1,7 @@ package project.trendpick_pro.domain.ask.repository; - -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; import project.trendpick_pro.domain.ask.entity.Ask; -import project.trendpick_pro.domain.member.entity.Member; public interface AskRepository extends JpaRepository, AskRepositoryCustom { - @Query("select a from Ask a where a.author = :member") - Page findAllByMember(Member member, Pageable pageable); } \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/domain/ask/repository/AskRepositoryCustom.java b/src/main/java/project/trendpick_pro/domain/ask/repository/AskRepositoryCustom.java index c4ab39fa..c44481cc 100644 --- a/src/main/java/project/trendpick_pro/domain/ask/repository/AskRepositoryCustom.java +++ b/src/main/java/project/trendpick_pro/domain/ask/repository/AskRepositoryCustom.java @@ -1,10 +1,7 @@ package project.trendpick_pro.domain.ask.repository; - import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import project.trendpick_pro.domain.ask.entity.Ask; -import project.trendpick_pro.domain.ask.entity.dto.request.AskByProductRequest; import project.trendpick_pro.domain.ask.entity.dto.response.AskResponse; public interface AskRepositoryCustom { diff --git a/src/main/java/project/trendpick_pro/domain/ask/service/AskService.java b/src/main/java/project/trendpick_pro/domain/ask/service/AskService.java index 7f76e97b..65566c41 100644 --- a/src/main/java/project/trendpick_pro/domain/ask/service/AskService.java +++ b/src/main/java/project/trendpick_pro/domain/ask/service/AskService.java @@ -1,82 +1,15 @@ package project.trendpick_pro.domain.ask.service; -import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import project.trendpick_pro.domain.ask.entity.Ask; import project.trendpick_pro.domain.ask.entity.dto.form.AskForm; import project.trendpick_pro.domain.ask.entity.dto.response.AskResponse; -import project.trendpick_pro.domain.ask.repository.AskRepository; import project.trendpick_pro.domain.member.entity.Member; -import project.trendpick_pro.domain.product.entity.product.Product; -import project.trendpick_pro.domain.product.repository.ProductRepository; import project.trendpick_pro.global.rsData.RsData; -import java.util.Objects; - -@Service -@Transactional(readOnly = true) -@RequiredArgsConstructor -public class AskService { - - private final AskRepository askRepository; - private final ProductRepository productRepository; - - //상품 상세에서 문의 내역 볼 때 - public Page showAsksByProduct(Long productId, int offset) { - Pageable pageable = PageRequest.of(offset, 10); - return askRepository.findAllByProductId(productId, pageable); - } - - public Page showAsksByMyPage(Member member, int offset) { - Pageable pageable = PageRequest.of(offset, 10); - Page asks = askRepository.findAllByMember(member, pageable); - return AskResponse.of(asks); - } - - public AskResponse show(Long askId) { - Ask ask = askRepository.findById(askId).orElseThrow(); - return AskResponse.of(ask); - } - - @Transactional - public RsData delete(Member member, Long askId) { - Ask ask = askRepository.findById(askId).orElseThrow(); - Long productId = ask.getProduct().getId(); - - if(!validateAccess(member, ask)) - return RsData.of("F-1", "해당 문의에 대한 삭제 권한이 없습니다."); - - askRepository.delete(ask); - return RsData.of("S-1", "상품 문의글이 삭제되었습니다.", productId); - } - - @Transactional - public RsData modify(Member member, Long askId, AskForm askForm) { - Ask ask = askRepository.findById(askId).orElseThrow(); - - if(!validateAccess(member, ask)) - return RsData.of("F-1", "해당 문의에 대한 수정 권한이 없습니다."); - - ask.update(askForm); - return RsData.of("S-1", "상품 문의글 수정이 정상적으로 처리되었습니다.", AskResponse.of(ask)); - } - - @Transactional - public RsData register(Member member, AskForm askForm) { - Product product = productRepository.findById(askForm.getProductId()).orElseThrow(null); - if(product == null) - return RsData.of("F-1", "해당 상품은 존재하지 않습니다."); - - Ask savedAsk = askRepository.save(Ask.of(member, product, askForm)); - return RsData.of("S-1", product.getName()+"에 대한 문의가 등록되었습니다.", savedAsk.getId()); - } - - - private boolean validateAccess(Member member, Ask ask) { - return Objects.equals(ask.getAuthor().getId(), member.getId()); - } +public interface AskService { + RsData register(Member member, AskForm askForm); + RsData modify(Member member, Long askId, AskForm askForm); + RsData delete(Member member, Long askId); + AskResponse show(Long askId); + Page showAsksByProduct(Long productId, int offset); } \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/domain/ask/service/impl/AskServiceImpl.java b/src/main/java/project/trendpick_pro/domain/ask/service/impl/AskServiceImpl.java new file mode 100644 index 00000000..eba52c56 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/ask/service/impl/AskServiceImpl.java @@ -0,0 +1,77 @@ +package project.trendpick_pro.domain.ask.service.impl; + +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.ask.entity.Ask; +import project.trendpick_pro.domain.ask.entity.dto.form.AskForm; +import project.trendpick_pro.domain.ask.entity.dto.response.AskResponse; +import project.trendpick_pro.domain.ask.exception.AskNotFoundException; +import project.trendpick_pro.domain.ask.exception.AskNotMatchException; +import project.trendpick_pro.domain.ask.repository.AskRepository; +import project.trendpick_pro.domain.ask.service.AskService; +import project.trendpick_pro.domain.member.entity.Member; +import project.trendpick_pro.domain.product.entity.product.Product; +import project.trendpick_pro.domain.product.service.ProductService; +import project.trendpick_pro.global.rsData.RsData; + +import java.util.Objects; + +@Service +@RequiredArgsConstructor +public class AskServiceImpl implements AskService { + + private final AskRepository askRepository; + private final ProductService productService; + + @Override + @Transactional + public RsData register(Member member, AskForm askForm) { + Product product = productService.findById(askForm.getProductId()); + Ask savedAsk = askRepository.save(Ask.of(member, product, askForm)); + return RsData.of("S-1", product.getName()+"에 대한 문의가 등록되었습니다.", savedAsk.getId()); + } + + @Override + @Transactional + public RsData modify(Member member, Long askId, AskForm askForm) { + Ask ask = getAskWithAuthValidation(member, askId); + ask.update(askForm); + return RsData.of("S-1", "상품 문의글 수정이 정상적으로 처리되었습니다.", AskResponse.of(ask)); + } + + @Override + @Transactional + public RsData delete(Member member, Long askId) { + Ask ask = getAskWithAuthValidation(member, askId); + askRepository.delete(ask); + return RsData.of("S-1", "상품 문의글이 삭제되었습니다.", ask.getProduct().getId()); + } + + @Override + @Transactional(readOnly = true) + public AskResponse show(Long askId) { + Ask ask = askRepository.findById(askId) + .orElseThrow(() -> new AskNotFoundException("해당 문의글은 존재하지 않습니다.")); + return AskResponse.of(ask); + } + + @Override + @Transactional(readOnly = true) + public Page showAsksByProduct(Long productId, int offset) { + Pageable pageable = PageRequest.of(offset, 10); + return askRepository.findAllByProductId(productId, pageable); + } + + private Ask getAskWithAuthValidation(Member member, Long askId) { + Ask ask = askRepository.findById(askId) + .orElseThrow(() -> new AskNotFoundException("해당 문의글은 존재하지 않습니다.")); + if (!Objects.equals(ask.getAuthor().getId(), member.getId())) { + throw new AskNotMatchException("해당 문의에 대한 권한이 없습니다."); + } + return ask; + } +} From 40eb1948da27e0d5649e6e83c1a280a02214527e Mon Sep 17 00:00:00 2001 From: SoohoLee Date: Mon, 10 Jul 2023 22:55:25 +0900 Subject: [PATCH 22/26] =?UTF-8?q?refactor:=20=EB=A9=A4=EB=B2=84=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81=20(#364)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/common/base/rq/Rq.java | 167 +++++--------- .../dto/request/StoreCouponSaveRequest.java | 9 +- .../dto/response/SimpleCouponResponse.java | 4 +- .../member/controller/MemberController.java | 48 +--- .../domain/member/entity/Member.java | 41 +++- .../domain/member/entity/RoleType.java | 9 + .../member/entity/dto/MemberInfoDto.java | 26 +-- .../domain/member/entity/form/JoinForm.java | 1 - .../member/repository/MemberRepository.java | 6 - .../domain/member/service/MemberService.java | 215 ++---------------- .../service/impl/MemberServiceImpl.java | 162 +++++++++++++ .../templates/trendpick/products/list.html | 15 +- .../trendpick/usr/layout/layout.html | 6 +- .../trendpick/usr/notification/list.html | 6 +- 14 files changed, 307 insertions(+), 408 deletions(-) create mode 100644 src/main/java/project/trendpick_pro/domain/member/service/impl/MemberServiceImpl.java diff --git a/src/main/java/project/trendpick_pro/domain/common/base/rq/Rq.java b/src/main/java/project/trendpick_pro/domain/common/base/rq/Rq.java index fda360fb..deb48bdf 100644 --- a/src/main/java/project/trendpick_pro/domain/common/base/rq/Rq.java +++ b/src/main/java/project/trendpick_pro/domain/common/base/rq/Rq.java @@ -5,9 +5,7 @@ import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; import org.springframework.context.MessageSource; -import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.User; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.context.annotation.RequestScope; @@ -33,13 +31,9 @@ public class Rq { private final MessageSource messageSource; private final LocaleResolver localeResolver; private Locale locale; - private final HttpServletRequest req; private final HttpServletResponse resp; private final HttpSession session; - private final User user; - - private Member member = null; // 레이지 로딩, 처음부터 넣지 않고, 요청이 들어올 때 넣는다. public Rq(MemberService memberService, MessageSource messageSource, LocaleResolver localeResolver, HttpServletRequest req, HttpServletResponse resp, HttpSession session) { @@ -50,105 +44,28 @@ public Rq(MemberService memberService, MessageSource messageSource, LocaleResolv this.resp = resp; this.session = session; - String username = SecurityContextHolder.getContext().getAuthentication().getName(); // 둘다 테스트 해보기 + String username = SecurityContextHolder.getContext().getAuthentication().getName(); Optional member = memberService.findByEmail(username); - if(member.isPresent()) - memberService.updateRecentlyAccessDate(member.get()); - - // 현재 로그인한 회원의 인증정보를 가져옴 - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - - if (authentication.getPrincipal() instanceof User) { - this.user = (User) authentication.getPrincipal(); - } else { - this.user = null; - } - } - - public String historyBack(String msg) { - String referer = req.getHeader("referer"); - String key = "historyBackErrorMsg___" + referer; - req.setAttribute("localStorageKeyAboutHistoryBackErrorMsg", key); - req.setAttribute("historyBackErrorMsg", msg); - // 200 이 아니라 400 으로 응답코드가 지정되도록 - resp.setStatus(HttpServletResponse.SC_BAD_REQUEST); - return "trendpick/common/js"; - } - - public String historyBack(RsData rsData) { - return historyBack(rsData.getMsg()); - } - public String redirectWithMsg(String url, RsData rsData) { - return redirectWithMsg(url, rsData.getMsg()); - } - public String redirectWithMsg(String url, String msg) { - return "redirect:" + urlWithMsg(url, msg); - } - private String urlWithMsg(String url, String msg) { - // 기존 URL에 혹시 msg 파라미터가 있다면 그것을 지우고 새로 넣는다. - return Ut.url.modifyQueryParam(url, "msg", msgWithTtl(msg)); - } - - private String getCurrentUrl() { - String url = req.getRequestURI(); - String queryStr = req.getQueryString(); - - if (StringUtils.hasText(queryStr)) { - url += "?" + queryStr; - } - - return url; - } - public String modifyQueryParam(String paramName, String paramValue) { - return Ut.url.modifyQueryParam(getCurrentUrl(), paramName, paramValue); - } - - private String msgWithTtl(String msg) { - return Ut.url.encode(msg) + ";ttl=" + new Date().getTime(); - } - - public boolean isLogin() { - return user != null; - } - public boolean isLogout() { - return !isLogin(); - } - public Member GetMember() { - if (isLogout()) return null; - - // 데이터가 없는지 체크 - if (member == null) { - member = memberService.findByUsername(user.getUsername()).orElseThrow(() -> new MemberNotFoundException("존재 하지 않는 회원입니다.")); - } - return member; + member.ifPresent(memberService::updateRecentlyAccessDate); } public Boolean checkLogin() { - - String username = SecurityContextHolder.getContext().getAuthentication().getName(); // 둘다 테스트 해보기 + String username = SecurityContextHolder.getContext().getAuthentication().getName(); Optional member = memberService.findByEmail(username); - return member.isPresent(); } public Member getLogin() { - - String username = SecurityContextHolder.getContext().getAuthentication().getName(); // 둘다 테스트 해보기 + String username = SecurityContextHolder.getContext().getAuthentication().getName(); Optional member = memberService.findByEmail(username); - if (member.isPresent()) { return member.get(); - } - else { + } else { throw new MemberNotFoundException("존재하지 않는 회원입니다."); } } - public Boolean checkMember() { return getLogin().getRole().equals(RoleType.MEMBER); } - public Boolean admin() { - return getLogin().getRole().equals(RoleType.ADMIN); - } public Member getMember() { Member member = getLogin(); if (member.getRole().equals(RoleType.MEMBER)) { @@ -157,21 +74,29 @@ public Member getMember() { throw new MemberNotMatchException("허용된 권한이 아닙니다."); } + public Boolean admin() { + return getLogin().getRole().equals(RoleType.ADMIN); + } public Member getRollMember(){ - return getLogin(); + Member member=getLogin(); + if(member.getRole().equals(RoleType.MEMBER)){ + return member; + } else if(member.getRole().equals(RoleType.BRAND_ADMIN)){ + return member; + } else if(member.getRole().equals(RoleType.ADMIN)){ + return member; + } + throw new MemberNotMatchException("허용된 권한이 아닙니다."); } public Member getBrandMember() { Member member = getLogin(); if (member.getRole().equals(RoleType.BRAND_ADMIN)) { return member; - } - throw new MemberNotMatchException("허용된 권한이 아닙니다."); + } throw new MemberNotMatchException("허용된 권한이 아닙니다."); } - public Boolean checkAdmin() { return !checkMember(); } - public Member getAdmin() { Member checkMember = getLogin(); if (checkMember.getRole().equals(RoleType.MEMBER)) { @@ -179,7 +104,6 @@ public Member getAdmin() { } return checkMember; } - public Boolean checkAdminOrBrand(){ if(!checkLogin()) { return false; @@ -187,7 +111,6 @@ public Boolean checkAdminOrBrand(){ return !getLogin().getRole().equals(RoleType.MEMBER); } } - public Boolean checkBrand() { return getLogin().getRole().equals(RoleType.BRAND_ADMIN); } @@ -199,33 +122,65 @@ public String getBrandName(){ public void setSessionAttr(String name, String value) { session.setAttribute(name, value); } - public T getSessionAttr(String name, T defaultValue) { try { return (T) session.getAttribute(name); - } catch (Exception ignored) { - } - + } catch (Exception ignored) {} return defaultValue; } - public void removeSessionAttr(String name) { session.removeAttribute(name); } - public String getCText(String code, String... args) { return messageSource.getMessage(code, args, getLocale()); } - private Locale getLocale() { - if (locale == null) locale = localeResolver.resolveLocale(req); - + if (locale == null) { + locale = localeResolver.resolveLocale(req); + } return locale; } - public String getParamsJsonStr() { Map parameterMap = req.getParameterMap(); - return Ut.json.toStr(parameterMap); } + + public String historyBack(String msg) { + String referer = req.getHeader("referer"); + String key = "historyBackErrorMsg___" + referer; + req.setAttribute("localStorageKeyAboutHistoryBackErrorMsg", key); + req.setAttribute("historyBackErrorMsg", msg); + resp.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return "trendpick/common/js"; + } + + public String historyBack(RsData rsData) { + return historyBack(rsData.getMsg()); + } + public String redirectWithMsg(String url, RsData rsData) { + return redirectWithMsg(url, rsData.getMsg()); + } + public String redirectWithMsg(String url, String msg) { + return "redirect:" + urlWithMsg(url, msg); + } + private String urlWithMsg(String url, String msg) { + return Ut.url.modifyQueryParam(url, "msg", msgWithTtl(msg)); + } + + private String getCurrentUrl() { + String url = req.getRequestURI(); + String queryStr = req.getQueryString(); + + if (StringUtils.hasText(queryStr)) { + url += "?" + queryStr; + } + return url; + } + + public String modifyQueryParam(String paramName, String paramValue) { + return Ut.url.modifyQueryParam(getCurrentUrl(), paramName, paramValue); + } + private String msgWithTtl(String msg) { + return Ut.url.encode(msg) + ";ttl=" + new Date().getTime(); + } } \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/domain/coupon/entity/dto/request/StoreCouponSaveRequest.java b/src/main/java/project/trendpick_pro/domain/coupon/entity/dto/request/StoreCouponSaveRequest.java index 58109b00..82c1b995 100644 --- a/src/main/java/project/trendpick_pro/domain/coupon/entity/dto/request/StoreCouponSaveRequest.java +++ b/src/main/java/project/trendpick_pro/domain/coupon/entity/dto/request/StoreCouponSaveRequest.java @@ -3,14 +3,13 @@ import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import lombok.*; -import org.springframework.stereotype.Service; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; import java.time.LocalDateTime; -@Getter -@Setter +@Data @NoArgsConstructor @AllArgsConstructor public class StoreCouponSaveRequest { diff --git a/src/main/java/project/trendpick_pro/domain/coupon/entity/dto/response/SimpleCouponResponse.java b/src/main/java/project/trendpick_pro/domain/coupon/entity/dto/response/SimpleCouponResponse.java index b3bd94e0..5056fc5f 100644 --- a/src/main/java/project/trendpick_pro/domain/coupon/entity/dto/response/SimpleCouponResponse.java +++ b/src/main/java/project/trendpick_pro/domain/coupon/entity/dto/response/SimpleCouponResponse.java @@ -8,7 +8,6 @@ import java.text.NumberFormat; import java.time.LocalDateTime; -import java.util.List; import java.util.Locale; @Getter @@ -43,13 +42,12 @@ public static SimpleCouponResponse of(Coupon coupon){ ); } - public String getFormattedMinimumPurchaseAmount(){ NumberFormat numberFormat = NumberFormat.getInstance(Locale.getDefault()); return numberFormat.format(getMinimumPurchaseAmount())+"원"; } + public int getRemaining(){ return getLimitCount() - getIssueCount(); } - } diff --git a/src/main/java/project/trendpick_pro/domain/member/controller/MemberController.java b/src/main/java/project/trendpick_pro/domain/member/controller/MemberController.java index f07943ca..43a2de20 100644 --- a/src/main/java/project/trendpick_pro/domain/member/controller/MemberController.java +++ b/src/main/java/project/trendpick_pro/domain/member/controller/MemberController.java @@ -23,7 +23,6 @@ import java.util.Optional; -@Slf4j @Controller @RequiredArgsConstructor @RequestMapping("/trendpick/member") @@ -46,14 +45,11 @@ public String register(JoinForm joinForm, Model model) { @PreAuthorize("isAnonymous()") @PostMapping("/register") public String register(@ModelAttribute @Valid JoinForm joinForm) { - RsData member = memberService.register(joinForm); if (member.isFail()) return rq.historyBack(member); - if(member.getData().getRole().getValue().equals("MEMBER")) recommendService.select(member.getData().getEmail()); - return rq.redirectWithMsg("/trendpick/member/login", member); } @@ -66,8 +62,7 @@ public String login() { @PreAuthorize("hasAuthority({'MEMBER'})") @GetMapping("/info") public String showMe(Model model) { - Member member = rq.getLogin(); - model.addAttribute("MemberInfo", MemberInfoDto.of(member)); + model.addAttribute("MemberInfo", MemberInfoDto.of(rq.getLogin())); return "trendpick/usr/member/info"; } @@ -81,60 +76,23 @@ public String registerAddress(AddressForm addressForm, Model model) { @PreAuthorize("hasAuthority({'MEMBER'})") @PostMapping("/info/address") public String manageAddress(@ModelAttribute @Valid AddressForm addressForm, Model model) { - RsData member = memberService.manageAddress(rq.getLogin(), addressForm.address()); model.addAttribute("MemberInfo", MemberInfoDto.of(member.getData())); - return rq.redirectWithMsg("/trendpick/member/info", member); } @PreAuthorize("hasAuthority({'MEMBER'})") @GetMapping("/edit/address") - public String editAddress(AddressForm addressForm, Model model) { + public String editAddress(Model model) { model.addAttribute("originalAdrress", rq.getMember().getAddress()); - model.addAttribute("addressForm", addressForm); return "trendpick/usr/member/address"; } @PreAuthorize("hasAuthority({'MEMBER'})") @PostMapping("/edit/address") - public String updateAddress(@ModelAttribute @Valid AddressForm addressForm, Model model) { - + public String editAddress(@ModelAttribute @Valid AddressForm addressForm, Model model) { RsData member = memberService.manageAddress(rq.getLogin(), addressForm.address()); model.addAttribute("MemberInfo", MemberInfoDto.of(member.getData())); - - return rq.redirectWithMsg("/trendpick/member/info", member); - } - - @PreAuthorize("hasAuthority({'MEMBER'})") - @GetMapping("/info/account") - public String registerAccount(AccountForm accountForm, Model model){ - model.addAttribute("accountForm", accountForm); - return "trendpick/usr/member/account"; - } - - @PreAuthorize("hasAuthority({'MEMBER'})") - @PostMapping("/info/account") - public String manageAccount(@ModelAttribute @Valid AccountForm accountForm, Model model) { - RsData member = memberService.manageAccount(rq.getLogin(), accountForm.bankName(), accountForm.bankAccount()); - model.addAttribute("MemberInfo", MemberInfoDto.of(member.getData())); - - return rq.redirectWithMsg("/trendpick/member/info", member); - } - - @PreAuthorize("hasAuthority({'MEMBER'})") - @GetMapping("/edit/account") - public String editAccount(AccountForm accountForm, Model model){ - model.addAttribute("accountForm", accountForm); - return "trendpick/usr/member/account"; - } - - @PreAuthorize("hasAuthority({'MEMBER'})") - @PostMapping("/edit/account") - public String updateAccount(@ModelAttribute @Valid AccountForm accountForm, Model model) { - RsData member = memberService.manageAccount(rq.getLogin(), accountForm.bankName(), accountForm.bankAccount()); - model.addAttribute("MemberInfo", MemberInfoDto.of(member.getData())); - return rq.redirectWithMsg("/trendpick/member/info", member); } } diff --git a/src/main/java/project/trendpick_pro/domain/member/entity/Member.java b/src/main/java/project/trendpick_pro/domain/member/entity/Member.java index 82ddb635..9f8254e5 100644 --- a/src/main/java/project/trendpick_pro/domain/member/entity/Member.java +++ b/src/main/java/project/trendpick_pro/domain/member/entity/Member.java @@ -1,9 +1,13 @@ package project.trendpick_pro.domain.member.entity; import jakarta.persistence.*; -import lombok.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; import project.trendpick_pro.domain.cart.entity.Cart; import project.trendpick_pro.domain.common.base.BaseTimeEntity; +import project.trendpick_pro.domain.member.entity.form.JoinForm; import project.trendpick_pro.domain.orders.entity.Order; import project.trendpick_pro.domain.tags.favoritetag.entity.FavoriteTag; import project.trendpick_pro.domain.tags.type.TagType; @@ -16,7 +20,6 @@ @Entity @Getter -@Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Table(name = "member", indexes = {@Index(name = "index_member_email", columnList="email", unique = true)}) @@ -45,6 +48,7 @@ public class Member extends BaseTimeEntity { @OneToOne(mappedBy = "member") private Cart cart; + @OneToMany(mappedBy = "member", cascade = CascadeType.ALL, orphanRemoval = true) private Set tags = new LinkedHashSet<>(); @@ -56,15 +60,38 @@ public class Member extends BaseTimeEntity { private String address; private LocalDateTime recentlyAccessDate; private long restCash; + @Builder - public Member(String email, String password, String username, String phoneNumber, RoleType role,long restCash) { + public Member(String email, String password, String username, String phoneNumber, RoleType role,String brand) { this.email = email; this.password = password; this.username = username; this.phoneNumber = phoneNumber; this.role = role; - this.restCash=restCash; + this.brand = brand; } + + public static Member of(JoinForm joinForm, String password, RoleType role, String brand) { + return Member.builder() + .email(joinForm.email()) + .password(password) + .username(joinForm.username()) + .phoneNumber(joinForm.phoneNumber()) + .role(role) + .brand(brand) + .build(); + } + + public static Member of(JoinForm joinForm, String password, RoleType role) { + return Member.builder() + .email(joinForm.email()) + .password(password) + .username(joinForm.username()) + .phoneNumber(joinForm.phoneNumber()) + .role(role) + .build(); + } + public void connectBrand(String brand){ this.brand = brand; } @@ -78,6 +105,10 @@ public void connectBank(String bankName, String bankAccount) { this.bankAccount = bankAccount; } + public void connectCash(long cash){ + this.restCash = cash; + } + public void changeTags(Set tags) { this.tags = tags; for(FavoriteTag tag : tags){ @@ -86,7 +117,6 @@ public void changeTags(Set tags) { } } - //양방향 메서드 public void addTag(FavoriteTag tag){ getTags().add(tag); tag.connectMember(this); @@ -95,5 +125,4 @@ public void addTag(FavoriteTag tag){ public void updateRecentlyAccessDate() { this.recentlyAccessDate = LocalDateTime.now(); } - } diff --git a/src/main/java/project/trendpick_pro/domain/member/entity/RoleType.java b/src/main/java/project/trendpick_pro/domain/member/entity/RoleType.java index 97111fa9..57ad75a7 100644 --- a/src/main/java/project/trendpick_pro/domain/member/entity/RoleType.java +++ b/src/main/java/project/trendpick_pro/domain/member/entity/RoleType.java @@ -14,4 +14,13 @@ public enum RoleType{ RoleType(String value) { this.value = value; } + + public static RoleType getRoleType(String value){ + return switch (value) { + case "ADMIN" -> ADMIN; + case "BRAND_ADMIN" -> BRAND_ADMIN; + case "MEMBER" -> MEMBER; + default -> null; + }; + } } diff --git a/src/main/java/project/trendpick_pro/domain/member/entity/dto/MemberInfoDto.java b/src/main/java/project/trendpick_pro/domain/member/entity/dto/MemberInfoDto.java index a556e1fd..c36e1435 100644 --- a/src/main/java/project/trendpick_pro/domain/member/entity/dto/MemberInfoDto.java +++ b/src/main/java/project/trendpick_pro/domain/member/entity/dto/MemberInfoDto.java @@ -1,25 +1,22 @@ package project.trendpick_pro.domain.member.entity.dto; -import com.fasterxml.jackson.annotation.JsonProperty; -import lombok.*; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; import project.trendpick_pro.domain.member.entity.Member; @Getter @NoArgsConstructor @Setter public class MemberInfoDto { - private String bankAccount; + private String bankAccount; private String address; - private String phone; - private String name; - private String bankName; - private String email; - private Long memberId; @Builder @@ -36,17 +33,4 @@ public MemberInfoDto (Member member) { public static MemberInfoDto of(Member member){ return new MemberInfoDto(member); } - - @Override - public String toString() { - return "MemberInfoDto{" + - "memberId=" + memberId + - ", name='" + name + '\'' + - ", email='" + email + '\'' + - ", phone='" + phone + '\'' + - ", address='" + address + '\'' + - ", bankName='" + bankName + '\'' + - ", bankAccount='" + bankAccount + '\'' + - '}'; - } } diff --git a/src/main/java/project/trendpick_pro/domain/member/entity/form/JoinForm.java b/src/main/java/project/trendpick_pro/domain/member/entity/form/JoinForm.java index cda06a5d..9202849f 100644 --- a/src/main/java/project/trendpick_pro/domain/member/entity/form/JoinForm.java +++ b/src/main/java/project/trendpick_pro/domain/member/entity/form/JoinForm.java @@ -1,7 +1,6 @@ package project.trendpick_pro.domain.member.entity.form; import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; import lombok.Builder; import java.util.List; diff --git a/src/main/java/project/trendpick_pro/domain/member/repository/MemberRepository.java b/src/main/java/project/trendpick_pro/domain/member/repository/MemberRepository.java index 53b0532f..dc0d1802 100644 --- a/src/main/java/project/trendpick_pro/domain/member/repository/MemberRepository.java +++ b/src/main/java/project/trendpick_pro/domain/member/repository/MemberRepository.java @@ -1,18 +1,12 @@ package project.trendpick_pro.domain.member.repository; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import project.trendpick_pro.domain.member.entity.Member; -import project.trendpick_pro.domain.member.entity.RoleType; -import java.time.LocalDateTime; import java.util.Optional; public interface MemberRepository extends JpaRepository { Optional findByUsername(String username); Optional findByEmail(String email); - Page findAllByRoleAndRecentlyAccessDateBetween(RoleType role, LocalDateTime fromDate, LocalDateTime toDate, Pageable pageable); - Member findByBrand(String brand); } \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/domain/member/service/MemberService.java b/src/main/java/project/trendpick_pro/domain/member/service/MemberService.java index 0033f3b8..03922e43 100644 --- a/src/main/java/project/trendpick_pro/domain/member/service/MemberService.java +++ b/src/main/java/project/trendpick_pro/domain/member/service/MemberService.java @@ -1,210 +1,25 @@ package project.trendpick_pro.domain.member.service; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import project.trendpick_pro.domain.brand.entity.Brand; -import project.trendpick_pro.domain.brand.service.BrandService; import project.trendpick_pro.domain.cash.entity.CashLog; -import project.trendpick_pro.domain.cash.service.CashService; -import project.trendpick_pro.domain.common.base.rq.Rq; +import project.trendpick_pro.domain.cash.entity.dto.CashResponse; import project.trendpick_pro.domain.member.entity.Member; -import project.trendpick_pro.domain.member.entity.RoleType; import project.trendpick_pro.domain.member.entity.form.JoinForm; -import project.trendpick_pro.domain.member.exception.MemberNotFoundException; -import project.trendpick_pro.domain.member.repository.MemberRepository; -import project.trendpick_pro.domain.recommend.service.RecommendService; -import project.trendpick_pro.domain.store.entity.Store; -import project.trendpick_pro.domain.store.service.StoreService; -import project.trendpick_pro.domain.tags.favoritetag.entity.FavoriteTag; import project.trendpick_pro.domain.tags.tag.entity.dto.request.TagRequest; import project.trendpick_pro.global.rsData.RsData; -import java.util.*; - -@Slf4j -@Service -@RequiredArgsConstructor -@Transactional(readOnly = true) -public class MemberService { - - private final PasswordEncoder passwordEncoder; - private final MemberRepository memberRepository; - private final RecommendService recommendService; - private final StoreService storeService; - - private final CashService cashService; - private final BrandService brandService; - private final Rq rq; - @Transactional - public RsData register(JoinForm joinForm) { - - if (memberRepository.findByEmail(joinForm.email()).isPresent()) { - return RsData.of("F-1", "해당 아이디(%s)는 이미 사용중입니다.".formatted(joinForm.email())); - } - - String brand = ""; - RoleType roleType; - if (Objects.equals(joinForm.state(), RoleType.ADMIN.getValue())) { - roleType = RoleType.ADMIN; - } else if (joinForm.state().equals(RoleType.BRAND_ADMIN.getValue())) { - roleType = RoleType.BRAND_ADMIN; - brand = joinForm.brand(); - } else { - roleType = RoleType.MEMBER; - } - Member member = Member - .builder() - .email(joinForm.email()) - .password(passwordEncoder.encode(joinForm.password())) - .username(joinForm.username()) - .phoneNumber(joinForm.phoneNumber()) - .role(roleType) - .build(); - member.connectBrand(brand); - - if(brand.length() != 0 && !brandService.isPresent(brand)){ - brandService.save(brand); - storeService.save(new Store(brand)); - } - - if (joinForm.tags() != null) { - Set favoriteTags = new LinkedHashSet<>(); - for (String tag : joinForm.tags()) { - FavoriteTag favoriteTag = new FavoriteTag(tag); - favoriteTags.add(favoriteTag); - } - member.changeTags(favoriteTags); - } - - Member savedMember = memberRepository.save(member); - recommendService.select(savedMember.getEmail()); - - return RsData.of("S-1", "회원가입이 완료되었습니다.", member); - } - - @Transactional - public List saveAll(List List) { - List list = new ArrayList<>(); - for (JoinForm joinForm : List) { - if (memberRepository.findByEmail(joinForm.email()).isPresent()) { - return null; - } - String brand = ""; - RoleType roleType; - if (Objects.equals(joinForm.state(), RoleType.ADMIN.getValue())) { - roleType = RoleType.ADMIN; - } else if (joinForm.state().equals(RoleType.BRAND_ADMIN.getValue())) { - roleType = RoleType.BRAND_ADMIN; - brand = joinForm.brand(); - } else { - roleType = RoleType.MEMBER; - } - Member member = Member - .builder() - .email(joinForm.email()) - .password(passwordEncoder.encode(joinForm.password())) - .username(joinForm.username()) - .phoneNumber(joinForm.phoneNumber()) - .role(roleType) - .build(); - member.connectBrand(brand); - - if(brand.length() != 0 && !brandService.isPresent(brand)){ - brandService.save(brand); - storeService.save(new Store(brand)); - } - - if (joinForm.tags() != null) { - Set favoriteTags = new LinkedHashSet<>(); - for (String tag : joinForm.tags()) { - FavoriteTag favoriteTag = new FavoriteTag(tag); - favoriteTags.add(favoriteTag); - } - member.changeTags(favoriteTags); - } - list.add(member); - } - memberRepository.saveAll(list); - return list; - } - - @Transactional - public void manageTag(String username, TagRequest tagRequest){ - - Member member = memberRepository.findByUsername(username).orElseThrow(() -> new MemberNotFoundException("존재하지 않는 회원입니다.")); - - Set tags = new LinkedHashSet<>(); - for (String tag : tagRequest.getTags()) { - FavoriteTag favoriteTag = new FavoriteTag(tag); - tags.add(favoriteTag); - } - member.changeTags(tags); - } - - @Transactional - public RsData manageAddress(Member member, String address){ - member.connectAddress(address); - return RsData.of("S-1", "주소 수정이 완료되었습니다.", member); - } - - @Transactional - public RsData manageAccount(Member member, String bank_name, String account){ - member.connectBank(bank_name, account); - return RsData.of("S-1", "계좌 수정이 완료되었습니다.", member); - } - - public Member findById(Long id) { - return memberRepository.findById(id).orElseThrow(() -> new MemberNotFoundException("존재하지 않는 회원입니다.")); - } - public Member findByBrandMember(String name){ - return memberRepository.findByBrand(name); - } - public Optional findByUsername(String username) { - return memberRepository.findByUsername(username); - } - - public Optional findByEmail(String username){ - return memberRepository.findByEmail(username); - } - - @Transactional - public void updateRecentlyAccessDate(Member member){ - member.updateRecentlyAccessDate(); - } - - @Data - @AllArgsConstructor - public static class AddCashRsDataBody { - CashLog cashLog; - long newRestCash; - } - - @Transactional - public RsData addCash(String brand, long price, Brand relEntity, CashLog.EvenType eventType) { - Member member=findByBrandMember(brand); - if(!member.getBrand().equals(brand)){ - return RsData.of("F-1","해당 브랜드와 관리자가 일치하지 않습니다."); - } - - CashLog cashLog = cashService.addCash(member, price, relEntity.getName(),relEntity.getId(), eventType); - - long newRestCash = getRestCash(member) + cashLog.getPrice(); - member.setRestCash(newRestCash); - memberRepository.save(member); - - return RsData.of( - "S-1", - "성공", - new AddCashRsDataBody(cashLog, newRestCash) - ); - } - public long getRestCash(Member member) { - System.out.println( memberRepository.findById(member.getId()).get().getRestCash()); - return memberRepository.findById(member.getId()).get().getRestCash(); - } +import java.util.List; +import java.util.Optional; + +public interface MemberService { + RsData register(JoinForm joinForm); + RsData> saveAll(List joinForms); + void manageTag(String username, TagRequest tagRequest); + RsData manageAddress(Member member, String address); + Member findById(Long id); + Member findByBrandMember(String name); + Optional findByEmail(String username); + void updateRecentlyAccessDate(Member member); + RsData addCash(String brand, long price, Brand relEntity, CashLog.EvenType eventType); + long getRestCash(Member member); } \ No newline at end of file diff --git a/src/main/java/project/trendpick_pro/domain/member/service/impl/MemberServiceImpl.java b/src/main/java/project/trendpick_pro/domain/member/service/impl/MemberServiceImpl.java new file mode 100644 index 00000000..96af93a2 --- /dev/null +++ b/src/main/java/project/trendpick_pro/domain/member/service/impl/MemberServiceImpl.java @@ -0,0 +1,162 @@ +package project.trendpick_pro.domain.member.service.impl; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import project.trendpick_pro.domain.brand.entity.Brand; +import project.trendpick_pro.domain.brand.service.BrandService; +import project.trendpick_pro.domain.cash.entity.CashLog; +import project.trendpick_pro.domain.cash.entity.dto.CashResponse; +import project.trendpick_pro.domain.cash.service.CashService; +import project.trendpick_pro.domain.member.entity.Member; +import project.trendpick_pro.domain.member.entity.RoleType; +import project.trendpick_pro.domain.member.entity.form.JoinForm; +import project.trendpick_pro.domain.member.exception.MemberNotFoundException; +import project.trendpick_pro.domain.member.repository.MemberRepository; +import project.trendpick_pro.domain.member.service.MemberService; +import project.trendpick_pro.domain.recommend.service.RecommendService; +import project.trendpick_pro.domain.store.entity.Store; +import project.trendpick_pro.domain.store.service.StoreService; +import project.trendpick_pro.domain.tags.favoritetag.entity.FavoriteTag; +import project.trendpick_pro.domain.tags.tag.entity.dto.request.TagRequest; +import project.trendpick_pro.global.rsData.RsData; + +import java.util.*; +import java.util.stream.Collectors; + +@Slf4j +@Service +@RequiredArgsConstructor +public class MemberServiceImpl implements MemberService { + + private final MemberRepository memberRepository; + + private final PasswordEncoder passwordEncoder; + private final RecommendService recommendService; + private final StoreService storeService; + private final CashService cashService; + private final BrandService brandService; + + private Member makeMember(JoinForm joinForm) { + RoleType roleType = RoleType.getRoleType(joinForm.state()); + Member member = Member.of(joinForm, passwordEncoder.encode(joinForm.password()), roleType); + if (roleType == RoleType.BRAND_ADMIN) { + member = Member.of(joinForm, passwordEncoder.encode(joinForm.password()), roleType, joinForm.brand()); + saveBrandAndStoreIfNotExists(joinForm.brand()); + } + if (joinForm.tags() != null) { + member.changeTags(createFavoriteTags(joinForm.tags())); + } + return member; + } + + @Transactional + @Override + public RsData register(JoinForm joinForm) { + if (isEmailInUse(joinForm.email())) { + return RsData.of("F-1", "해당 아이디(%s)는 이미 사용중입니다.".formatted(joinForm.email())); + } + Member member = makeMember(joinForm); + Member savedMember = memberRepository.save(member); + recommendService.select(savedMember.getEmail()); + return RsData.of("S-1", "회원가입이 완료되었습니다.", member); + } + + @Transactional + @Override + public RsData> saveAll(List joinForms) { + List members = new ArrayList<>(); + for (JoinForm joinForm : joinForms) { + if (isEmailInUse(joinForm.email())) { + return RsData.of("F-1", "해당 아이디(%s)는 이미 사용중입니다.".formatted(joinForm.email())); + } + members.add(makeMember(joinForm)); + } + memberRepository.saveAll(members); + return RsData.of("S-1", "회원가입이 완료되었습니다.", members); + } + + @Transactional + @Override + public void manageTag(String username, TagRequest tagRequest){ + Member member = memberRepository.findByUsername(username).orElseThrow(() -> new MemberNotFoundException("존재하지 않는 회원입니다.")); + Set tags = new LinkedHashSet<>(); + for (String tag : tagRequest.getTags()) { + FavoriteTag favoriteTag = new FavoriteTag(tag); + tags.add(favoriteTag); + } + member.changeTags(tags); + } + + @Transactional + @Override + public RsData manageAddress(Member member, String address){ + member.connectAddress(address); + return RsData.of("S-1", "주소 수정이 완료되었습니다.", member); + } + + @Transactional(readOnly = true) + @Override + public Member findById(Long id) { + return memberRepository.findById(id).orElseThrow(() -> new MemberNotFoundException("존재하지 않는 회원입니다.")); + } + @Transactional(readOnly = true) + @Override + public Member findByBrandMember(String name){ + return memberRepository.findByBrand(name); + } + + @Transactional(readOnly = true) + @Override + public Optional findByEmail(String username){ + return memberRepository.findByEmail(username); + } + + @Transactional + @Override + public void updateRecentlyAccessDate(Member member){ + member.updateRecentlyAccessDate(); + } + + @Transactional + @Override + public RsData addCash(String brand, long price, Brand relEntity, CashLog.EvenType eventType) { + Member member=findByBrandMember(brand); + if(!member.getBrand().equals(brand)){ + return RsData.of("F-1","해당 브랜드와 관리자가 일치하지 않습니다."); + } + + CashLog cashLog = cashService.addCash(member, price, relEntity.getName(),relEntity.getId(), eventType); + + long newRestCash = getRestCash(member) + cashLog.getPrice(); + member.connectCash(newRestCash); + memberRepository.save(member); + + return RsData.of("S-1", "성공", new CashResponse(cashLog, newRestCash)); + } + + @Transactional(readOnly = true) + @Override + public long getRestCash(Member member) { + return memberRepository.findById(member.getId()).get().getRestCash(); + } + + private boolean isEmailInUse(String email) { + return memberRepository.findByEmail(email).isPresent(); + } + + private void saveBrandAndStoreIfNotExists(String brand) { + if (!brandService.isPresent(brand)) { + brandService.save(brand); + storeService.save(new Store(brand)); + } + } + + private Set createFavoriteTags(List tagList) { + return tagList.stream() + .map(FavoriteTag::new) + .collect(Collectors.toSet()); + } +} \ No newline at end of file diff --git a/src/main/resources/templates/trendpick/products/list.html b/src/main/resources/templates/trendpick/products/list.html index 36446d27..8c6a1e93 100644 --- a/src/main/resources/templates/trendpick/products/list.html +++ b/src/main/resources/templates/trendpick/products/list.html @@ -17,7 +17,7 @@ class="mx-1 my-1 px-2 py-1 bg-gray-300 rounded-full text-sm font-medium text-gray-700 hover:bg-gray-400"> -
+
@@ -25,17 +25,16 @@ 새 상품 생성
-
+
-
-
-
- Product Image +
+
+ Product Image

@@ -52,14 +51,12 @@

+
-
diff --git a/src/main/resources/templates/trendpick/usr/layout/layout.html b/src/main/resources/templates/trendpick/usr/layout/layout.html index 49c9558e..4d046e90 100644 --- a/src/main/resources/templates/trendpick/usr/layout/layout.html +++ b/src/main/resources/templates/trendpick/usr/layout/layout.html @@ -40,7 +40,7 @@