Skip to content

Commit

Permalink
Merge pull request #68 from jupyter471/weekly
Browse files Browse the repository at this point in the history
[jupyter -> weekly] 상품 업로드 로직 수정 및 감상평 기능 일부
  • Loading branch information
yooonwodyd authored Nov 2, 2024
2 parents c812e98 + c1b4a02 commit 4a31669
Show file tree
Hide file tree
Showing 14 changed files with 220 additions and 72 deletions.
32 changes: 13 additions & 19 deletions src/main/java/com/helpmeCookies/global/utils/AwsS3FileUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.helpmeCookies.product.dto.FileUploadResponse;
import com.helpmeCookies.product.dto.ImageUpload;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
Expand All @@ -14,7 +14,6 @@

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
Expand All @@ -28,26 +27,21 @@ public class AwsS3FileUtils {
private String bucket;

//다중파일 업로드후 url 반환
public List<FileUploadResponse> uploadMultiImages(List<MultipartFile> multipartFiles) {
List<FileUploadResponse> fileList = new ArrayList<>();
public ImageUpload uploadMultiImages(MultipartFile multipartFile) {

multipartFiles.forEach(file -> {
String fileName = createFileName(file.getOriginalFilename()); //파일 이름 난수화
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(file.getSize());
objectMetadata.setContentType(file.getContentType());
String fileName = createFileName(multipartFile.getOriginalFilename()); //파일 이름 난수화
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(multipartFile.getSize());
objectMetadata.setContentType(multipartFile.getContentType());

try (InputStream inputStream = file.getInputStream()) {
amazonS3.putObject(new PutObjectRequest(bucket, fileName, inputStream, objectMetadata)
.withCannedAcl(CannedAccessControlList.PublicRead));
} catch (IOException e) {
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "파일 업로드 실패" + fileName);
}

fileList.add(new FileUploadResponse(amazonS3.getUrl(bucket,fileName).toString(),fileName));
});
try (InputStream inputStream = multipartFile.getInputStream()) {
amazonS3.putObject(new PutObjectRequest(bucket, fileName, inputStream, objectMetadata)
.withCannedAcl(CannedAccessControlList.PublicRead));
} catch (IOException e) {
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "파일 업로드 실패" + fileName);
}

return fileList;
return new ImageUpload(amazonS3.getUrl(bucket,fileName).toString());
}

public String createFileName(String fileName) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.helpmeCookies.product.controller;

import com.helpmeCookies.product.dto.ImageUpload;
import static com.helpmeCookies.product.util.SortUtil.convertProductSort;

import com.helpmeCookies.product.controller.docs.ProductApiDocs;
import com.helpmeCookies.product.dto.FileUploadResponse;
import com.helpmeCookies.product.dto.ProductImageResponse;
import com.helpmeCookies.product.dto.ProductPage;
import com.helpmeCookies.product.dto.ProductRequest;
Expand All @@ -18,7 +18,6 @@
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;

@RestController
Expand All @@ -31,20 +30,22 @@ public class ProductController implements ProductApiDocs {

@PostMapping
public ResponseEntity<Void> saveProduct(@RequestBody ProductRequest productRequest) {
productService.save(productRequest);
Product product = productService.save(productRequest);
productImageService.saveImages(product.getId(),productRequest.imageUrls());
return ResponseEntity.ok().build();
}

@PostMapping("/{productId}/images")
public ResponseEntity<ProductImageResponse> uploadImages(@PathVariable("productId") Long productId, List<MultipartFile> files) throws IOException {
List<FileUploadResponse> responses = productImageService.uploadMultiFiles(productId,files);
return ResponseEntity.ok(new ProductImageResponse(responses.stream().map(FileUploadResponse::photoUrl).toList()));
@PostMapping("/images")
public ResponseEntity<ProductImageResponse> uploadImages(List<MultipartFile> files) {
List<ImageUpload> responses = productImageService.uploadMultiFiles(files);
return ResponseEntity.ok(new ProductImageResponse(responses.stream().map(ImageUpload::photoUrl).toList()));
}

@GetMapping("/{productId}")
public ResponseEntity<ProductResponse> getProductInfo(@PathVariable("productId") Long productId) {
Product product = productService.find(productId);
return ResponseEntity.ok(ProductResponse.from(product));
List<String> urls = productImageService.getImages(productId);
return ResponseEntity.ok(ProductResponse.from(product,urls));
}

@PutMapping("/{productId}")
Expand All @@ -55,8 +56,11 @@ public ResponseEntity<Void> editProductInfo(@PathVariable("productId") Long prod
}

@PutMapping("/{productId}/images")
public ResponseEntity<Void> editImages(@PathVariable("productId") Long productId, List<MultipartFile> files) throws IOException {
public ResponseEntity<Void> editImages(@PathVariable("productId") Long productId, List<MultipartFile> files) {
productImageService.editImages(productId, files);
List<String> images = productImageService.uploadMultiFiles(files).stream()
.map(ImageUpload::photoUrl).toList();
productImageService.saveImages(productId,images);
return ResponseEntity.ok().build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@

import com.helpmeCookies.product.entity.ProductImage;

public record FileUploadResponse(
String photoUrl,
String uuid
public record ImageUpload(
String photoUrl
) {
public ProductImage toEntity(Long productId) {
return ProductImage.builder()
.productId(productId)
.photoUrl(photoUrl)
.uuid(uuid)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ public record ProductRequest(
String description,
String preferredLocation,
List<HashTag> hashTags,
Long artistInfo
Long artistInfoId,
List<String> imageUrls

) {
public Product toEntity(ArtistInfo artistInfo) {
return Product.builder()
Expand Down
28 changes: 6 additions & 22 deletions src/main/java/com/helpmeCookies/product/dto/ProductResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,13 @@ public record ProductResponse(
String description,
String preferredLocation,
List<HashTag> hashTags,
ArtistInfo artistInfo
ArtistInfo artistInfo,
List<String> imageUrls
) {
public static class ArtistInfo {
private final Long artistId;
private final String name;

public ArtistInfo(Long artistId, String name) {
this.artistId = artistId;
this.name = name;
}

public Long getArtistId() {
return artistId;
}

public String getName() {
return name;
}
public record ArtistInfo(Long artistId, String artistName) {
}

public static ProductResponse from(Product product) {
//TODO artistInfo 코드 개발 이후 수정 예정
public static ProductResponse from(Product product, List<String> urls) {
return new ProductResponse(
product.getId(),
product.getName(),
Expand All @@ -45,9 +30,8 @@ public static ProductResponse from(Product product) {
product.getDescription(),
product.getPreferredLocation(),
product.getHashTags(),
new ArtistInfo(
1L, "임시"
)
new ArtistInfo(product.getArtistInfo().getId(),product.getArtistInfo().getNickname()),
urls
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@ public ProductImage(String photoUrl, Long productId, String uuid) {
this.productId = productId;
this.uuid = uuid;
}

public String getPhotoUrl() {
return photoUrl;
}
}

Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package com.helpmeCookies.product.service;

import com.helpmeCookies.global.utils.AwsS3FileUtils;
import com.helpmeCookies.product.dto.FileUploadResponse;
import com.helpmeCookies.product.dto.ImageUpload;
import com.helpmeCookies.product.entity.ProductImage;
import com.helpmeCookies.product.repository.ProductImageRepository;
import java.util.ArrayList;
import com.helpmeCookies.product.repository.ProductRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;

@Service
Expand All @@ -20,22 +21,30 @@ public class ProductImageService {
private final ProductRepository productRepository;

@Transactional
public List<FileUploadResponse> uploadMultiFiles(Long productId, List<MultipartFile> files) throws IOException {
List<FileUploadResponse> uploadResponses = awsS3FileUtils.uploadMultiImages(files);
uploadResponses.forEach(response ->
productImageRepository.save(response.toEntity(productId)));

var product = productRepository.findById(productId).orElseThrow(() -> new IllegalArgumentException("유효하지 않은 id입니다"));
product.updateThumbnail(uploadResponses.getFirst().photoUrl());
public List<ImageUpload> uploadMultiFiles(List<MultipartFile> files) {
List<ImageUpload> imageUploads = new ArrayList<>();
for (MultipartFile multipartFile:files) {
imageUploads.add(awsS3FileUtils.uploadMultiImages(multipartFile));
}
return imageUploads;
}

return uploadResponses;
@Transactional
public void saveImages(Long productId,List<String> urls) {
//DTO 변환
List<ImageUpload> files = urls.stream().map(ImageUpload::new).toList();
files.forEach(image -> productImageRepository.save(image.toEntity(productId)));
}

@Transactional
public void editImages(Long productId, List<MultipartFile> files) throws IOException {
public void editImages(Long productId, List<MultipartFile> files) {
//우선은 전부 삭제하고 다시 업로드
//추후에 개선 예정
//TODO s3서버에서 기존 사진들을 제거하는 기능
productImageRepository.deleteAllByProductId(productId);
uploadMultiFiles(productId, files);
}

public List<String> getImages(Long productId) {
return productImageRepository.findAllByProductId(productId).stream().map(ProductImage::getPhotoUrl).toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import com.helpmeCookies.product.entity.Product;
import com.helpmeCookies.product.repository.ProductImageRepository;
import com.helpmeCookies.product.repository.ProductRepository;
import com.helpmeCookies.user.entity.ArtistInfo;
import com.helpmeCookies.user.repository.ArtistInfoRepository;
import com.helpmeCookies.product.dto.ProductPage;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
Expand All @@ -16,6 +18,7 @@
public class ProductService {
private final ProductRepository productRepository;
private final ProductImageRepository productImageRepository;
private final ArtistInfoRepository artistInfoRepository;

@Transactional(readOnly = true)
public ProductPage.Paging getProductsByPage(String query, Pageable pageable) {
Expand All @@ -24,8 +27,9 @@ public ProductPage.Paging getProductsByPage(String query, Pageable pageable) {
}

public Product save(ProductRequest productSaveRequest) {
//TODO ArtistInfo 코드 병합시 수정 예정
Product product = productSaveRequest.toEntity(null);
ArtistInfo artistInfo = artistInfoRepository.findById(productSaveRequest.artistInfoId())
.orElseThrow(() -> new IllegalArgumentException("유효하지 않은 작가 정보입니다."));
Product product = productSaveRequest.toEntity(artistInfo);
productRepository.save(product);
return product;
}
Expand All @@ -37,7 +41,8 @@ public Product find(Long productId) {
@Transactional
public void edit(Long productId, ProductRequest productRequest) {
Product product = productRepository.findById(productId).orElseThrow(() -> new IllegalArgumentException("유효하지 않은 id입니다"));
//TODO ArtistInfo 코드 병합시 수정 예정
ArtistInfo artistInfo = artistInfoRepository.findById(productRequest.artistInfoId())
.orElseThrow(() -> new IllegalArgumentException("유효하지 않은 작가 정보입니다."));
product.update(
productRequest.name(),
Category.fromString(productRequest.category()),
Expand All @@ -46,7 +51,7 @@ public void edit(Long productId, ProductRequest productRequest) {
productRequest.description(),
productRequest.preferredLocation(),
productRequest.hashTags(),
null);
artistInfo);
}

public void delete(Long productId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.helpmeCookies.review.controller;

import com.helpmeCookies.review.dto.ReviewRequest;
import com.helpmeCookies.review.dto.ReviewResponse;
import com.helpmeCookies.review.entity.Review;
import com.helpmeCookies.review.service.ReviewService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/v1/reviews")
@RequiredArgsConstructor
public class ReviewController {

private final ReviewService reviewService;

//TODO 감상평 삭제
//TODO 해당 상품의 감상평 조회
//TODO 내 감상평 조회

@PostMapping("/{productId}")
public ResponseEntity<Void> postReview(@RequestBody ReviewRequest request, @PathVariable Long productId) {
reviewService.saveReview(request, productId);
return ResponseEntity.ok().build();
}

@PutMapping("/{productId}/{reviewId}")
public ResponseEntity<Void> editReview(@RequestBody ReviewRequest request, @PathVariable Long productId, @PathVariable Long reviewId) {
reviewService.editReview(request, productId, reviewId);
return ResponseEntity.ok().build();
}

@GetMapping("/{reviewId}")
public ResponseEntity<ReviewResponse> getReview(@PathVariable Long reviewId) {
Review response = reviewService.getReview(reviewId);
return ResponseEntity.ok(ReviewResponse.fromEntity(response));
}
}
15 changes: 15 additions & 0 deletions src/main/java/com/helpmeCookies/review/dto/ReviewRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.helpmeCookies.review.dto;

import com.helpmeCookies.product.entity.Product;
import com.helpmeCookies.review.entity.Review;
import com.helpmeCookies.user.entity.User;

public record ReviewRequest(Long writerId, String content) {
public Review toEntity(User writer, Product product) {
return Review.builder()
.content(content)
.writer(writer)
.product(product)
.build();
}
}
11 changes: 11 additions & 0 deletions src/main/java/com/helpmeCookies/review/dto/ReviewResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.helpmeCookies.review.dto;

import com.helpmeCookies.product.entity.Product;
import com.helpmeCookies.review.entity.Review;
import com.helpmeCookies.user.entity.User;

public record ReviewResponse(Long id, String content,User writer, Product product) {
public static ReviewResponse fromEntity(Review review) {
return new ReviewResponse(review.getId(), review.getContent(),review.getWriter(), review.getProduct());
}
}
Loading

0 comments on commit 4a31669

Please sign in to comment.