Skip to content

Commit

Permalink
Merge pull request #36 from closeup-raffle/feature/create-raffle-product
Browse files Browse the repository at this point in the history
[FEAT] 래플 생성하기
  • Loading branch information
thisishwan2 authored Jan 8, 2024
2 parents 7b4e3a6 + 6a90da3 commit 1193c22
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 18 deletions.
1 change: 1 addition & 0 deletions src/main/java/farmSystem/closeUp/common/Result.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public enum Result {
NOTFOUND_RAFFLE(404, "해당 래플이 존재하지 않습니다."),
RAFFLE_END(404, "래플 응모가 마감됐습니다."),
NOT_ENOUGH_POINT(404, "응모할 포인트가 부족합니다"),
NOTFOUND_CATEGORY(404, "해당 카테고리가 존재하지 않습니다."),

// 포인트
LESS_THAN_MINIMUM_POINT(400, "5000원 이상부터 충전이 가능합니다."),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package farmSystem.closeUp.config;
package farmSystem.closeUp.config.s3;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
Expand Down
71 changes: 71 additions & 0 deletions src/main/java/farmSystem/closeUp/config/s3/S3Uploader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package farmSystem.closeUp.config.s3;

import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.PutObjectRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Optional;

@Slf4j
@RequiredArgsConstructor
@Component
public class S3Uploader {
private final AmazonS3Client amazonS3Client;

@Value("${cloud.aws.s3.bucket}")
private String bucket;

// MultipartFile을 전달받아 File로 전환한 후 S3에 업로드
public String upload(MultipartFile multipartFile, String dirName) throws IOException {
File uploadFile = convert(multipartFile)
.orElseThrow(() -> new IllegalArgumentException("MultipartFile -> File 전환 실패"));
return upload(uploadFile, dirName);
}

private String upload(File uploadFile, String dirName) {
String fileName = dirName + "/" + uploadFile.getName();
String uploadImageUrl = putS3(uploadFile, fileName);

removeNewFile(uploadFile); // 로컬에 생성된 File 삭제 (MultipartFile -> File 전환 하며 로컬에 파일 생성됨)

return uploadImageUrl; // 업로드된 파일의 S3 URL 주소 반환
}

private void removeNewFile(File targetFile) {
if(targetFile.delete()) {
log.info("파일이 삭제되었습니다.");
}else {
log.info("파일이 삭제되지 못했습니다.");
}
}


private String putS3(File uploadFile, String fileName) {
amazonS3Client.putObject(
new PutObjectRequest(bucket, fileName, uploadFile)
.withCannedAcl(CannedAccessControlList.PublicRead) // PublicRead 권한으로 업로드 됨
);
return amazonS3Client.getUrl(bucket, fileName).toString();
}


private Optional<File> convert(MultipartFile file) throws IOException {
File convertFile = new File(file.getOriginalFilename());
if(convertFile.createNewFile()) {
try (FileOutputStream fos = new FileOutputStream(convertFile)) {
fos.write(file.getBytes());
}
return Optional.of(convertFile);
}
return Optional.empty();
}

}
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
package farmSystem.closeUp.controller;

import farmSystem.closeUp.common.CommonResponse;
import farmSystem.closeUp.dto.raffleProduct.response.GetRaffleProductApplyResponse;
import farmSystem.closeUp.dto.raffleProduct.response.GetRaffleProductResponse;
import farmSystem.closeUp.dto.raffleProduct.response.GetRaffleProductsResponse;
import farmSystem.closeUp.dto.raffleProduct.response.PostRaffleProductResponse;
import farmSystem.closeUp.dto.raffleProduct.request.PostCreateRaffleProductRequest;
import farmSystem.closeUp.dto.raffleProduct.response.*;
import farmSystem.closeUp.service.RaffleProductService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.naming.AuthenticationException;
import java.io.IOException;

@RestController
@Slf4j
Expand Down Expand Up @@ -70,4 +72,10 @@ public CommonResponse<GetRaffleProductApplyResponse> getOrder(@PathVariable("raf
public CommonResponse<PostRaffleProductResponse> postRaffleProduct(@PathVariable("raffleProductId") Long raffleProductId){
return CommonResponse.success(raffleProductService.postRaffleProduct(raffleProductId));
}

// 래플 생성하기
@PostMapping(value = "/creator/raffle-products", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public CommonResponse<PostCreateRaffleProductResponse> postCreateRaffleProduct(@RequestParam(value="thumbnailImage") MultipartFile thumbnailImage, @Valid final PostCreateRaffleProductRequest postCreateRaffleProductRequest) throws IOException {
return CommonResponse.success(raffleProductService.postCreateRaffleProduct(thumbnailImage, postCreateRaffleProductRequest));
}
}
17 changes: 17 additions & 0 deletions src/main/java/farmSystem/closeUp/domain/RaffleProduct.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,21 @@ public class RaffleProduct extends BaseEntity{
private Category category;

@Builder
public RaffleProduct(Long raffleProductId, String title, LocalDate startDate, LocalDate endDate, String content, Long winnerCount, Long rafflePrice, String address, LocalDateTime winningDate, String thumbnailImageUrl, User creator, Category category) {
this.raffleProductId = raffleProductId;
this.title = title;
this.startDate = startDate;
this.endDate = endDate;
this.content = content;
this.winnerCount = winnerCount;
this.rafflePrice = rafflePrice;
this.address = address;
this.winningDate = winningDate;
this.thumbnailImageUrl = thumbnailImageUrl;
this.creator = creator;
this.category = category;
}

public RaffleProduct(Long raffleProductId, String title, LocalDate startDate, LocalDate endDate, String content, Long winnerCount, Long rafflePrice, String address, LocalDateTime winningDate, String thumbnailImageUrl) {
this.raffleProductId = raffleProductId;
this.title = title;
Expand All @@ -57,5 +72,7 @@ public RaffleProduct(Long raffleProductId, String title, LocalDate startDate, Lo
this.address = address;
this.winningDate = winningDate;
this.thumbnailImageUrl = thumbnailImageUrl;
this.creator = creator;
this.category = category;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package farmSystem.closeUp.dto.raffleProduct.request;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PostCreateRaffleProductExtraRequest {
private String file;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package farmSystem.closeUp.dto.raffleProduct.request;

import lombok.Builder;
import lombok.Getter;

import java.time.LocalDateTime;

@Builder
@Getter
public class PostCreateRaffleProductRequest {
private String title;
private LocalDateTime startDate;
private LocalDateTime endDate;
private String content;
private Long winnerCount;
private Long rafflePrice;
private Long categoryId;
private PostCreateRaffleProductExtraRequest extraRequest;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package farmSystem.closeUp.dto.raffleProduct.response;

import lombok.Builder;
import lombok.Getter;

import java.time.LocalDateTime;

@Getter
@Builder
public class PostCreateRaffleProductResponse {
private LocalDateTime winnerDate;

public static PostCreateRaffleProductResponse of(LocalDateTime winnerDate) {
return PostCreateRaffleProductResponse.builder()
.winnerDate(winnerDate)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package farmSystem.closeUp.repository.category;

import farmSystem.closeUp.domain.Category;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface CategoryRepository extends JpaRepository<Category, Long> {
Optional<Category> findByCategoryId(Long id);
}
74 changes: 61 additions & 13 deletions src/main/java/farmSystem/closeUp/service/RaffleProductService.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,29 @@

import farmSystem.closeUp.common.CustomException;
import farmSystem.closeUp.common.Result;
import farmSystem.closeUp.config.s3.S3Uploader;
import farmSystem.closeUp.domain.*;
import farmSystem.closeUp.dto.raffleProduct.response.GetRaffleProductApplyResponse;
import farmSystem.closeUp.dto.raffleProduct.response.GetRaffleProductResponse;
import farmSystem.closeUp.dto.raffleProduct.response.GetRaffleProductsResponse;
import farmSystem.closeUp.dto.raffleProduct.response.PostRaffleProductResponse;
import farmSystem.closeUp.dto.raffleProduct.request.PostCreateRaffleProductRequest;
import farmSystem.closeUp.dto.raffleProduct.response.*;
import farmSystem.closeUp.repository.category.CategoryRepository;
import farmSystem.closeUp.repository.follow.FollowRepository;
import farmSystem.closeUp.repository.pointHistory.PointHistoryRepository;
import farmSystem.closeUp.repository.raffle.RaffleRepository;

import farmSystem.closeUp.repository.follow.FollowRepository;
import farmSystem.closeUp.repository.raffleProduct.RaffleProductRepository;
import farmSystem.closeUp.repository.raffleProduct.RaffleProductRepositoryImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.naming.AuthenticationException;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collections;
Expand All @@ -33,13 +35,18 @@
@Slf4j
@RequiredArgsConstructor
public class RaffleProductService {
@Autowired
private S3Uploader s3Uploader;

private final RaffleProductRepository raffleProductRepository;
private final RaffleProductRepositoryImpl raffleProductRepositoryImpl;
private final FollowRepository followRepository;
private final UserService userService;
private final RaffleRepository raffleRepository;
private final PointHistoryRepository pointHistoryRepository;
private final CategoryRepository categoryRepository;



// 회원님이 팔로우하는 크리에이터 래플 목록 조회
@Transactional(readOnly = true)
Expand All @@ -58,7 +65,7 @@ public Slice<GetRaffleProductsResponse> getFollowingRaffleProducts(Pageable page
// 아무도 팔로우 안한 경우 빈 리스트 반환
if (followList.isEmpty()) {
creatorIds = Collections.emptyList();
}else {
} else {
creatorIds = followList
.stream()
.map(follow -> follow.getCreator().getUserId())
Expand All @@ -71,29 +78,28 @@ public Slice<GetRaffleProductsResponse> getFollowingRaffleProducts(Pageable page
try {
Slice<GetRaffleProductsResponse> followingRaffleProducts = raffleProductRepositoryImpl.findFollowingRaffleProducts(creatorIds, pageable);
return followingRaffleProducts;
}
catch (Exception e) {
} catch (Exception e) {
throw new CustomException(Result.NOTFOUND_RAFFLE);
}
}

// 전체 래플 목록 조회
@Transactional(readOnly = true)
public Slice<GetRaffleProductsResponse> getRaffleProducts(Pageable pageable){
public Slice<GetRaffleProductsResponse> getRaffleProducts(Pageable pageable) {
Sort sort = Sort.by(Sort.Direction.DESC, "createdAt");
PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);

try {
Slice<GetRaffleProductsResponse> raffleProducts = raffleProductRepositoryImpl.findRaffleProducts(pageable);
return raffleProducts;
}catch (Exception e) {
} catch (Exception e) {
throw new CustomException(Result.NOTFOUND_RAFFLE);
}
}

// 래플 상세 조회
@Transactional(readOnly = true)
public GetRaffleProductResponse getRaffleProduct(Long raffleProductId){
public GetRaffleProductResponse getRaffleProduct(Long raffleProductId) {
RaffleProduct raffleProduct = raffleProductRepository.findById(raffleProductId).orElseThrow(() -> new CustomException(Result.NOTFOUND_RAFFLE));
GetRaffleProductResponse getRaffleProductResponse = GetRaffleProductResponse.
of(raffleProduct.getRaffleProductId(), raffleProduct.getTitle(), raffleProduct.getStartDate(), raffleProduct.getEndDate(), raffleProduct.getContent(), raffleProduct.getWinnerCount(), raffleProduct.getRafflePrice(), raffleProduct.getWinningDate(), raffleProduct.getThumbnailImageUrl(), raffleProduct.getCreator().getNickName(), raffleProduct.getCreator().getUserId());
Expand Down Expand Up @@ -133,7 +139,7 @@ public PostRaffleProductResponse postRaffleProduct(Long raffleProductId) {
throw new CustomException(Result.RAFFLE_END);
}

if (user.getPoint() - raffleProduct.getRafflePrice()<0){
if (user.getPoint() - raffleProduct.getRafflePrice() < 0) {
throw new CustomException(Result.NOT_ENOUGH_POINT);
}

Expand Down Expand Up @@ -169,4 +175,46 @@ public Slice<GetRaffleProductsResponse> getCreatorRaffleProducts(Long creatorId,

return findRaffles;
}

@Transactional
public PostCreateRaffleProductResponse postCreateRaffleProduct(MultipartFile thumbnailImage, PostCreateRaffleProductRequest postCreateRaffleProductRequest) throws IOException {
// 현재 크리에이터 조회
User user = userService.getCurrentUser();

// 카테고리 조회
Category category = categoryRepository.findByCategoryId(postCreateRaffleProductRequest.getCategoryId()).orElseThrow(() -> new CustomException(Result.NOTFOUND_CATEGORY));

// 당첨자 발표 날짜 구하기 - 래플 종료 일 정오 12시
LocalDateTime endDate = postCreateRaffleProductRequest.getEndDate();
LocalDateTime winningDate = endDate.plusDays(0).withHour(12).withMinute(0).withSecond(0).withNano(0);

// 섬네일 이미지 s3에 저장
String thumbnailImageUrl = null;
if(!thumbnailImage.isEmpty()) {
String storedFileName = s3Uploader.upload(thumbnailImage, "raffle_thumbnail");
thumbnailImageUrl = storedFileName;
}

// 래플 상품 생성
RaffleProduct raffleProduct = RaffleProduct.builder()
.title(postCreateRaffleProductRequest.getTitle())
.startDate(postCreateRaffleProductRequest.getStartDate())
.endDate(postCreateRaffleProductRequest.getEndDate())
.winningDate(winningDate)
.content(postCreateRaffleProductRequest.getContent())
.winnerCount(postCreateRaffleProductRequest.getWinnerCount())
.rafflePrice(postCreateRaffleProductRequest.getRafflePrice())
.thumbnailImageUrl(thumbnailImageUrl)
.creator(user)
.category(category)
.build();

// 무형인지 유형인지 판단
// if (category.getParent().getCategoryId() == Long.valueOf(2)) {
// raffleProduct.
// }

raffleProductRepository.save(raffleProduct);
return PostCreateRaffleProductResponse.of(winningDate);
}
}

0 comments on commit 1193c22

Please sign in to comment.