Skip to content

Commit

Permalink
Merge pull request #12 from Team-Flory/chore/#11/s3-setting
Browse files Browse the repository at this point in the history
[Chore] 이미지 세팅
  • Loading branch information
junseokkim authored Nov 14, 2023
2 parents 2be15fa + 2016a5e commit 760aea6
Show file tree
Hide file tree
Showing 19 changed files with 318 additions and 10 deletions.
6 changes: 4 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ dependencies {
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'


// swagger
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0")
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'

// s3
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package zerobibim.flory.domain.Image.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import zerobibim.flory.domain.Image.dto.response.ImageIdResponse;
import zerobibim.flory.domain.Image.service.ImageService;
import zerobibim.flory.global.common.ApiPayload.ApiResponse;

@Tag(name = "Image API", description = "이미지 관련 API")
@RestController
@RequiredArgsConstructor
@RequestMapping("/image")
public class ImageConroller {
private final ImageService imageService;

@PostMapping
@Operation(summary = "이미지 생성 API")
public ApiResponse<ImageIdResponse> createImage(@RequestPart("flower_image") MultipartFile flowerImage) {
return ApiResponse.onSuccess(imageService.createImage(flowerImage));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package zerobibim.flory.domain.Image.dto.response;

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

@Getter
@AllArgsConstructor
@NoArgsConstructor
public class ImageIdResponse {
private Long ImageId;
}
41 changes: 41 additions & 0 deletions src/main/java/zerobibim/flory/domain/Image/entity/Image.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package zerobibim.flory.domain.Image.entity;

import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.Where;
import zerobibim.flory.global.common.BaseTime;

@Entity
@Getter
@Where(clause = "deleted_at is null")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Image extends BaseTime {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false)
private String url;

private Long senderId;

private Long receiverId;

private Boolean isNFT;

@Builder
public Image(String url) {
this.url = url;
this.senderId = null;
this.receiverId = null;
this.isNFT = Boolean.FALSE;
}

public void updateImage(Long senderId, Long receiverId) {
this.senderId = senderId;
this.receiverId = receiverId;
this.isNFT = Boolean.TRUE;
}
}
13 changes: 13 additions & 0 deletions src/main/java/zerobibim/flory/domain/Image/mapper/ImageMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package zerobibim.flory.domain.Image.mapper;

import org.springframework.stereotype.Component;
import zerobibim.flory.domain.Image.entity.Image;

@Component
public class ImageMapper {
public Image toEntity(String url) {
return Image.builder()
.url(url)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package zerobibim.flory.domain.Image.repository;

import zerobibim.flory.domain.Image.entity.Image;

import java.util.Optional;

public interface ImageRepository {

Image save(Image image);

Optional<Image> findImageById(Long id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package zerobibim.flory.domain.Image.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import zerobibim.flory.domain.Image.entity.Image;

public interface JpaImageRepository extends JpaRepository<Image, Long>, ImageRepository {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package zerobibim.flory.domain.Image.service;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import zerobibim.flory.domain.Image.dto.response.ImageIdResponse;
import zerobibim.flory.domain.Image.entity.Image;
import zerobibim.flory.domain.Image.mapper.ImageMapper;
import zerobibim.flory.domain.Image.repository.ImageRepository;
import zerobibim.flory.global.common.ApiPayload.code.status.ErrorStatus;
import zerobibim.flory.global.common.EntityLoader;
import zerobibim.flory.global.common.ExceptionHandler;
import zerobibim.flory.utils.S3ImageComponent;

import java.util.Optional;

@Service
@RequiredArgsConstructor
public class ImageService implements EntityLoader<Image, Long> {

private final ImageMapper imageMapper;
private final ImageRepository imageRepository;
private final S3ImageComponent s3ImageComponent;

@Transactional
public ImageIdResponse createImage(final MultipartFile flowerImage) {
String imageUrl = uploadImage(flowerImage);

Image newImage = imageRepository.save(
imageMapper.toEntity(imageUrl));
return new ImageIdResponse(newImage.getId());
}

private String uploadImage(final MultipartFile flowerImage) {
if(flowerImage.isEmpty()) {
throw new ExceptionHandler(ErrorStatus.IMAGE_BLANK);
}
return s3ImageComponent.uploadImage("flower-image", flowerImage);
}

@Transactional
public void makeNft(Long imageId, Long senderId, Long receiverId) {
Image image = loadEntity(imageId);
image.updateImage(senderId, receiverId);
}

@Override
public Image loadEntity(Long id) {
Optional<Image> image = imageRepository.findImageById(id);
if(image.isEmpty()) throw new ExceptionHandler(ErrorStatus.IMAGE_NOT_FOUND);
return image.get();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import zerobibim.flory.domain.flower.dto.request.FlowerInsertImageRequest;
import zerobibim.flory.domain.flower.dto.request.FlowerCreateReqeust;
import zerobibim.flory.domain.flower.dto.request.FlowerUpdateRequest;
import zerobibim.flory.domain.flower.dto.response.FlowerDetailResponse;
Expand Down Expand Up @@ -42,6 +43,17 @@ public ApiResponse<FlowerIdResponse> updateFlower(@RequestBody FlowerUpdateReque
return ApiResponse.onSuccess(flowerService.updateFlower(request));
}

/**
* 꽃 이미지를 업데이트합니다.
* @param request 업데이트 할 꽃과 이미지에 대한 DTO입니다.
* @return 업데이트된 꽃의 id가 반환됩니다.
*/
@PostMapping("/image")
@Operation(summary = "꽃 이미지 생성 API")
public ApiResponse<FlowerIdResponse> insertImage(@RequestBody FlowerInsertImageRequest request) {
return ApiResponse.onSuccess(flowerService.insertImage(request));
}

/**
* 꽃 전체 정보를 조회합니다.
* @return 꽃 전체 정보를 리스트로 반환합니다.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package zerobibim.flory.domain.flower.dto.request;

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

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class FlowerInsertImageRequest {
private Long flowerId;
private Long imageId;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.Where;
import zerobibim.flory.domain.Image.entity.Image;
import zerobibim.flory.global.common.BaseTime;

@Entity
Expand All @@ -24,6 +25,10 @@ public class Flower extends BaseTime {
@Column(nullable = false)
private Long price;

@OneToOne
@JoinColumn
private Image image;

@Builder
public Flower(String name, String description, Long price) {
this.name = name;
Expand All @@ -35,4 +40,8 @@ public void update(String description, Long price) {
this.description = description;
this.price = price;
}

public void updateFlowerImage(Image image) {
this.image = image;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import zerobibim.flory.domain.Image.entity.Image;
import zerobibim.flory.domain.Image.service.ImageService;
import zerobibim.flory.domain.flower.dto.request.FlowerInsertImageRequest;
import zerobibim.flory.domain.flower.dto.request.FlowerCreateReqeust;
import zerobibim.flory.domain.flower.dto.request.FlowerUpdateRequest;
import zerobibim.flory.domain.flower.dto.response.FlowerDetailResponse;
Expand All @@ -22,6 +25,7 @@
public class FlowerService implements EntityLoader<Flower, Long> {
private final FlowerRepository flowerRepository;
private final FlowerMapper flowerMapper;
private final ImageService imageService;

public FlowerIdResponse createFlower(FlowerCreateReqeust reqeust) {
// 중복 꽃 여부 확인
Expand All @@ -45,6 +49,15 @@ public FlowerIdResponse updateFlower(FlowerUpdateRequest request) {
return new FlowerIdResponse(flower.getId());
}

@Transactional
public FlowerIdResponse insertImage(FlowerInsertImageRequest request) {
Flower flower = loadEntity(request.getFlowerId());
Image image = imageService.loadEntity(request.getImageId());

flower.updateFlowerImage(image);
return new FlowerIdResponse(flower.getId());
}

public List<FlowerDetailResponse> findAllFlower() {
return flowerRepository.findAll().stream().map(flowerMapper::toResponse).toList();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ public class PurchaseCreateRequest {
private String receiverNickname;
private Long flowerId;
private int flowerQuentity;
private String nftComment;
private LocalDate receiveDate;
private int deliveryTip;
private int totalPrice;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ public class Purchase extends BaseTime {

private int flowerCnt;

private String nftComment;

private int deliveryTip;

private int totalPrice;
Expand All @@ -50,15 +48,14 @@ public class Purchase extends BaseTime {
@Builder
public Purchase(Member sender, Member receiver, LocalDate receiveDate,
Flower flower, String receiverName, String receiverAddress,
int flowerCnt, String nftComment, int deliveryTip, int totalPrice) {
int flowerCnt, int deliveryTip, int totalPrice) {
this.sender = sender;
this.receiver = receiver;
this.receiveDate = receiveDate;
this.receiverName = receiverName;
this.receiverAddress = receiverAddress;
this.flower = flower;
this.flowerCnt = flowerCnt;
this.nftComment = nftComment;
this.deliveryTip = deliveryTip;
this.totalPrice = totalPrice;
this.isDelivered = Boolean.FALSE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
public class PurchaseMapper {
public Purchase toEntity(Member sender, Member receiver, LocalDate receiveDate,
Flower flower, String receiverName, String receiverAddress,
int flowerCnt, String nftComment, int deliveryTip, int totalPrice) {
int flowerCnt, int deliveryTip, int totalPrice) {
return Purchase.builder()
.sender(sender)
.receiver(receiver)
Expand All @@ -20,7 +20,6 @@ public Purchase toEntity(Member sender, Member receiver, LocalDate receiveDate,
.receiverName(receiverName)
.receiverAddress(receiverAddress)
.flowerCnt(flowerCnt)
.nftComment(nftComment)
.deliveryTip(deliveryTip)
.totalPrice(totalPrice)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import zerobibim.flory.domain.Image.service.ImageService;
import zerobibim.flory.domain.flower.entity.Flower;
import zerobibim.flory.domain.flower.service.FlowerService;
import zerobibim.flory.domain.member.entity.Member;
Expand All @@ -24,16 +25,19 @@ public class PurchaseService implements EntityLoader<Purchase, Long> {
private final PurchaseMapper purchaseMapper;
private final MemberService memberService;
private final FlowerService flowerService;
private final ImageService imageService;

public PurchaseIdResponse createPurchase(PurchaseCreateRequest request) {
Member sender = memberService.loadEntity(request.getMemberId());
Member receiver = memberService.findMemberByNickname(request.getReceiverNickname());
Flower flower = flowerService.loadEntity(request.getFlowerId());
if(flower.getImage() == null) throw new ExceptionHandler(ErrorStatus.NO_IMAGE_IN_FLOWER);
imageService.makeNft(flower.getImage().getId(), sender.getId(), receiver.getId());

Purchase newPurchase = purchaseRepository.save(
purchaseMapper.toEntity(
sender, receiver, request.getReceiveDate(), flower, request.getReceiverName(), request.getReceiverAddress(),
request.getFlowerQuentity(), request.getNftComment(), request.getDeliveryTip(), request.getTotalPrice()
request.getFlowerQuentity(), request.getDeliveryTip(), request.getTotalPrice()
));

return new PurchaseIdResponse(newPurchase.getId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public enum ErrorStatus implements BaseErrorCode {
// 꽃 관련 응답
FLOWER_NOT_FOUND(HttpStatus.BAD_REQUEST, "FLOWER4001", "존재하지 않는 꽃입니다."),
FLOWER_EXISTED(HttpStatus.BAD_REQUEST, "FLOWER4002","이미 존재하는 꽃입니다."),
NO_IMAGE_IN_FLOWER(HttpStatus.BAD_REQUEST, "FLOWER4003", "꽃에 이미지가 존재하지 않습니다."),
// 기념일 관련 응답

// 구매 관련 응답
Expand All @@ -33,6 +34,10 @@ public enum ErrorStatus implements BaseErrorCode {

// 테스트 관련 응답
TEST_EXCEPTION(HttpStatus.BAD_REQUEST, "TEST4001", "테스트를 위한 에러 코드"),

// 이미지 관련 응답
IMAGE_BLANK(HttpStatus.BAD_REQUEST, "IMAGE4001", "이미지 파일이 없습니다."),
IMAGE_NOT_FOUND(HttpStatus.BAD_REQUEST, "IMAGE4002", "존재하지 않는 이미지입니다."),
;


Expand Down
Loading

0 comments on commit 760aea6

Please sign in to comment.