Skip to content

Commit

Permalink
Feat/#92,#93/일자별 응모 정보 어드민 기능 추가, 퀴즈 어드민 이미지 처리 (#94)
Browse files Browse the repository at this point in the history
* [FEAT] 퀴즈 이미지 S3에 업로드 기능 추가

* [FiX] 퀴즈 정답 수정 요청에서 이미지를 멀티파트로 받도록 수정

* [FiX] 퀴즈 정답 정보 엔티티 업데이트 메소드 수정

* [FiX] 퀴즈 에러 코드 추가

* [FiX] 응모 에러코드 추가

* [FEAT] 일자별 응모 정보 응답 객체 추가

* [FEAT] 일자별 응모 정보 수정 요청 객체 추가

* [FEAT] 일자별 응모 정보 업데이트 메서드, 생성자 추가

* [FEAT] 일자별 응모 정보 수정/생성 기능 구현

* [FEAT] 일자별 응모 정보 수정/생성/조회 엔드포인트 추가

* [FEAT] 검증 메시지 추가

* [FEAT] 응모 수정/생성 요청 객체 검증 처리
  • Loading branch information
devchlee12 authored Aug 16, 2024
1 parent 54733b0 commit 0a8e91b
Show file tree
Hide file tree
Showing 11 changed files with 262 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
package softeer.team_pineapple_be.domain.admin.controller;

import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
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;

import java.time.LocalDate;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import softeer.team_pineapple_be.domain.draw.request.DrawDailyMessageModifyRequest;
import softeer.team_pineapple_be.domain.draw.request.DrawPrizeRequest;
import softeer.team_pineapple_be.domain.draw.response.DrawDailyMessageResponse;
import softeer.team_pineapple_be.domain.draw.service.DrawPrizeService;
import softeer.team_pineapple_be.domain.draw.service.DrawService;
import softeer.team_pineapple_be.domain.quiz.dao.QuizDao;
import softeer.team_pineapple_be.domain.quiz.domain.QuizInfo;
import softeer.team_pineapple_be.domain.quiz.exception.QuizErrorCode;
Expand All @@ -36,6 +46,7 @@ public class AdminController {
private final QuizService quizService;
private final QuizDao quizDao;
private final DrawPrizeService drawPrizeService;
private final DrawService drawService;

@Operation(summary = "날짜에 해당하는 퀴즈 정보 가져오기")
@GetMapping("/quiz/{day}")
Expand All @@ -52,6 +63,13 @@ public ResponseEntity<QuizAnswerResponse> getDailyQuizAnswer(@PathVariable("day"
return ResponseEntity.ok(QuizAnswerResponse.of(quizInfo));
}

@Operation(summary = "일자별 응모 정보 가져오기")
@GetMapping("/draw/daily-info/{day}")
public ResponseEntity<DrawDailyMessageResponse> getDrawDailyMessageInfo(@PathVariable("day") LocalDate day) {
DrawDailyMessageResponse dailyMessageInfo = drawService.getDailyMessageInfo(day);
return ResponseEntity.ok(dailyMessageInfo);
}

@Operation(summary = "퀴즈 등록/수정하기")
@PutMapping("/quiz/{day}")
public ResponseEntity<SuccessResponse> updateDailyQuiz(@PathVariable("day") LocalDate day,
Expand All @@ -63,11 +81,19 @@ public ResponseEntity<SuccessResponse> updateDailyQuiz(@PathVariable("day") Loca
@Operation(summary = "퀴즈 정답 정보 등록/수정")
@PutMapping("/quiz/answers/{day}")
public ResponseEntity<SuccessResponse> updateDailyQuizAnswer(@PathVariable("day") LocalDate day,
@RequestBody QuizInfoModifyRequest quizInfoModifyRequest) {
@ModelAttribute QuizInfoModifyRequest quizInfoModifyRequest) {
quizService.modifyOrSaveQuizInfo(day, quizInfoModifyRequest);
return ResponseEntity.ok(new SuccessResponse());
}

@Operation(summary = "일자별 응모 정보 등록/수정")
@PutMapping("/draw/daily-info")
public ResponseEntity<SuccessResponse> updateDrawDailyMessageInfo(
@ModelAttribute DrawDailyMessageModifyRequest drawDailyMessageModifyRequest) {
drawService.updateOrSaveDailyMessageInfo(drawDailyMessageModifyRequest);
return ResponseEntity.ok(new SuccessResponse());
}

@Operation(summary = "응모 경품(바코드)이미지 등록 및 삭제")
@PostMapping("/drawPrize")
public ResponseEntity<SuccessResponse> uploadDrawPrize(@Valid @ModelAttribute DrawPrizeRequest drawPrizeRequest) {
Expand All @@ -77,7 +103,8 @@ public ResponseEntity<SuccessResponse> uploadDrawPrize(@Valid @ModelAttribute Dr

@Operation(summary = "선착순 경품(바코드)이미지 등록 및 삭제")
@PostMapping("/quizReward")
public ResponseEntity<SuccessResponse> uploadQuizReward(@ModelAttribute QuizRewardUploadRequest quizRewardUploadRequest) {
public ResponseEntity<SuccessResponse> uploadQuizReward(
@ModelAttribute QuizRewardUploadRequest quizRewardUploadRequest) {
quizService.uploadQuizRewardZipFile(quizRewardUploadRequest.getFile(), quizRewardUploadRequest.getQuizDate());
return ResponseEntity.ok(new SuccessResponse());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -34,5 +35,30 @@ public class DrawDailyMessageInfo {
@Column(nullable = false)
private String loseImage;
@Column(nullable = false)
private String commonScenario;
@Column(nullable = false)
private LocalDate drawDate;

@Builder
public DrawDailyMessageInfo(String winMessage, String loseMessage, String loseScenario, String winImage,
String loseImage, String commonScenario, LocalDate drawDate) {
this.winMessage = winMessage;
this.loseMessage = loseMessage;
this.loseScenario = loseScenario;
this.winImage = winImage;
this.loseImage = loseImage;
this.commonScenario = commonScenario;
this.drawDate = drawDate;
}

public void update(String winMessage, String loseMessage, String loseScenario, String winImage, String loseImage,
String commonScenario, LocalDate drawDate) {
this.winMessage = winMessage;
this.loseMessage = loseMessage;
this.loseScenario = loseScenario;
this.winImage = winImage;
this.loseImage = loseImage;
this.commonScenario = commonScenario;
this.drawDate = drawDate;
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
package softeer.team_pineapple_be.domain.draw.exception;

import org.springframework.http.HttpStatus;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import softeer.team_pineapple_be.global.exception.ErrorCode;

@Getter
@RequiredArgsConstructor
public enum DrawErrorCode implements ErrorCode {

NO_PRIZE(HttpStatus.BAD_REQUEST, "상품이 존재하지 않습니다."),
CANNOT_ENTER_DRAW(HttpStatus.BAD_REQUEST, "상품 응모 조건에 부합하지 않습니다."),
NO_VALID_PRIZE(HttpStatus.BAD_REQUEST, "상품의 개수와 유효성이 일치하지 않습니다."),
NOT_PRIZE_OWNER(HttpStatus.BAD_REQUEST, " 해당 상품의 당첨자가 아닙니다."),
NOT_VALID_DATE(HttpStatus.BAD_REQUEST, "상품 추첨이 가능하지 않은 날짜입니다.");
NO_PRIZE(HttpStatus.BAD_REQUEST, "상품이 존재하지 않습니다."),
CANNOT_ENTER_DRAW(HttpStatus.BAD_REQUEST, "상품 응모 조건에 부합하지 않습니다."),
NO_VALID_PRIZE(HttpStatus.BAD_REQUEST, "상품의 개수와 유효성이 일치하지 않습니다."),
NOT_PRIZE_OWNER(HttpStatus.BAD_REQUEST, " 해당 상품의 당첨자가 아닙니다."),
NOT_VALID_DATE(HttpStatus.BAD_REQUEST, "상품 추첨이 가능하지 않은 날짜입니다."),
NO_DAILY_INFO(HttpStatus.BAD_REQUEST, "일자별 응모 정보가 존재하지 않습니다"),
DAILY_INFO_WIN_IMAGE_UPLOAD_FAILED(HttpStatus.BAD_REQUEST, "응모 성공 이미지 업로드에 실패했습니다."),
DAILY_INFO_LOSE_IMAGE_UPLOAD_FAILED(HttpStatus.BAD_REQUEST, "응모 실패 이미지 업로드에 실패했습니다.");

private final HttpStatus httpStatus;
private final String message;
private final HttpStatus httpStatus;
private final String message;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package softeer.team_pineapple_be.domain.draw.request;

import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDate;

import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

/**
* 일자별 응모 정보 수정 요청 객체
*/
@NoArgsConstructor
@AllArgsConstructor
@Setter
@Getter
public class DrawDailyMessageModifyRequest {
@NotNull(message = "{draw.win_message_required}")
private String winMessage;
@NotNull(message = "{draw.lose_message_required}")
private String loseMessage;
@NotNull(message = "{draw.lose_scenario_required}")
private String loseScenario;
@NotNull(message = "{draw.win_image_required}")
private MultipartFile winImage;
@NotNull(message = "{draw.lose_image_required}")
private MultipartFile loseImage;
@NotNull(message = "{draw.common_scenario_required}")
private String commonScenario;
@NotNull(message = "{draw.draw_date_required}")
private LocalDate drawDate;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package softeer.team_pineapple_be.domain.draw.response;

import java.time.LocalDate;

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

/**
* 일자별 응모 정보 응답 객체
*/
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Builder
public class DrawDailyMessageResponse {
private String winMessage;
private String loseMessage;
private String loseScenario;
private String winImage;
private String loseImage;
private String commonScenario;
private LocalDate drawDate;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Optional;

import lombok.RequiredArgsConstructor;
import softeer.team_pineapple_be.domain.comment.repository.CommentRepository;
Expand All @@ -18,13 +20,17 @@
import softeer.team_pineapple_be.domain.draw.repository.DrawHistoryRepository;
import softeer.team_pineapple_be.domain.draw.repository.DrawPrizeRepository;
import softeer.team_pineapple_be.domain.draw.repository.DrawRewardInfoRepository;
import softeer.team_pineapple_be.domain.draw.request.DrawDailyMessageModifyRequest;
import softeer.team_pineapple_be.domain.draw.response.DrawDailyMessageResponse;
import softeer.team_pineapple_be.domain.draw.response.DrawLoseResponse;
import softeer.team_pineapple_be.domain.draw.response.DrawResponse;
import softeer.team_pineapple_be.domain.draw.response.DrawWinningResponse;
import softeer.team_pineapple_be.domain.member.domain.Member;
import softeer.team_pineapple_be.domain.member.exception.MemberErrorCode;
import softeer.team_pineapple_be.domain.member.repository.MemberRepository;
import softeer.team_pineapple_be.global.auth.service.AuthMemberService;
import softeer.team_pineapple_be.global.cloud.service.S3DeleteService;
import softeer.team_pineapple_be.global.cloud.service.S3UploadService;
import softeer.team_pineapple_be.global.exception.RestApiException;

/**
Expand All @@ -33,6 +39,8 @@
@Service
@RequiredArgsConstructor
public class DrawService {
public static final String DAILY_DRAW_WIN_FOLDER = "daily-win-image/";
public static final String DAILY_DRAW_LOSE_FOLDER = "daily-lose-image/";
private final DrawDailyMessageInfoRepository drawDailyMessageInfoRepository;
private final DrawHistoryRepository drawHistoryRepository;
private final DrawPrizeRepository drawPrizeRepository;
Expand All @@ -41,6 +49,8 @@ public class DrawService {
private final MemberRepository memberRepository;
private final RandomDrawPrizeService randomDrawPrizeService;
private final CommentRepository commentRepository;
private final S3UploadService s3UploadService;
private final S3DeleteService s3DeleteService;

/**
* 경품 추첨 수행하는 메서드
Expand Down Expand Up @@ -77,6 +87,65 @@ public DrawResponse enterDraw() {
dailyMessageInfo.getWinImage(), prizeId, member.isCar(), member.getToolBoxCnt());
}

/**
* 일자별 응모 메시지 가져오기
*
* @param date
* @return
*/
@Transactional(readOnly = true)
public DrawDailyMessageResponse getDailyMessageInfo(LocalDate date) {
DrawDailyMessageInfo dailyMessageInfo = drawDailyMessageInfoRepository.findByDrawDate(date)
.orElseThrow(() -> new RestApiException(
DrawErrorCode.NO_DAILY_INFO));
return DrawDailyMessageResponse.builder()
.winMessage(dailyMessageInfo.getWinMessage())
.loseMessage(dailyMessageInfo.getLoseMessage())
.loseScenario(dailyMessageInfo.getLoseScenario())
.winImage(dailyMessageInfo.getWinImage())
.winMessage(dailyMessageInfo.getWinMessage())
.loseImage(dailyMessageInfo.getLoseImage())
.commonScenario(dailyMessageInfo.getCommonScenario())
.drawDate(dailyMessageInfo.getDrawDate())
.build();
}

/**
* 일자별 메시지 정보 수정/등록
*
* @param drawDailyMessageModifyRequest
*/
@Transactional
public void updateOrSaveDailyMessageInfo(DrawDailyMessageModifyRequest drawDailyMessageModifyRequest) {
String winImageFolder = DAILY_DRAW_WIN_FOLDER + drawDailyMessageModifyRequest.getDrawDate() + "/";
String loseImageFolder = DAILY_DRAW_LOSE_FOLDER + drawDailyMessageModifyRequest.getDrawDate() + "/";
Optional<DrawDailyMessageInfo> byDrawDate =
drawDailyMessageInfoRepository.findByDrawDate(drawDailyMessageModifyRequest.getDrawDate());
if (byDrawDate.isPresent()) { // 수정
DrawDailyMessageInfo dailyMessageInfo = byDrawDate.get();
s3DeleteService.deleteFolder(winImageFolder);
s3DeleteService.deleteFolder(loseImageFolder);
ImageUrls imageUrls = uploadDrawInfoImages(drawDailyMessageModifyRequest, winImageFolder, loseImageFolder);
dailyMessageInfo.update(drawDailyMessageModifyRequest.getWinMessage(),
drawDailyMessageModifyRequest.getLoseMessage(), drawDailyMessageModifyRequest.getLoseScenario(),
imageUrls.winImageUrl, imageUrls.loseImageUrl, drawDailyMessageModifyRequest.getCommonScenario(),
drawDailyMessageModifyRequest.getDrawDate());
return;
}
ImageUrls imageUrls = uploadDrawInfoImages(drawDailyMessageModifyRequest, winImageFolder, loseImageFolder);
drawDailyMessageInfoRepository.save(DrawDailyMessageInfo.builder()
.winMessage(drawDailyMessageModifyRequest.getWinMessage())
.loseMessage(drawDailyMessageModifyRequest.getLoseMessage())
.loseScenario(
drawDailyMessageModifyRequest.getLoseScenario())
.winImage(imageUrls.winImageUrl)
.loseImage(imageUrls.loseImageUrl)
.commonScenario(
drawDailyMessageModifyRequest.getCommonScenario())
.drawDate(drawDailyMessageModifyRequest.getDrawDate())
.build());
}

/**
* 경품 추첨 자격 있는지 확인
*
Expand All @@ -102,4 +171,24 @@ private Long setPrizeOwner(DrawRewardInfo rewardInfo, String memberPhoneNumber)
prize.invalidate();
return prize.getId();
}

private ImageUrls uploadDrawInfoImages(DrawDailyMessageModifyRequest drawDailyMessageModifyRequest,
String winImageFolder, String loseImageFolder) {
String winImageUrl;
String loseImageUrl;
try {
winImageUrl = s3UploadService.saveFile(drawDailyMessageModifyRequest.getWinImage(), winImageFolder);
} catch (IOException e) {
throw new RestApiException(DrawErrorCode.DAILY_INFO_WIN_IMAGE_UPLOAD_FAILED);
}
try {
loseImageUrl = s3UploadService.saveFile(drawDailyMessageModifyRequest.getLoseImage(), loseImageFolder);
} catch (IOException e) {
throw new RestApiException(DrawErrorCode.DAILY_INFO_LOSE_IMAGE_UPLOAD_FAILED);
}
return new ImageUrls(winImageUrl, loseImageUrl);
}

private record ImageUrls(String winImageUrl, String loseImageUrl) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import softeer.team_pineapple_be.domain.quiz.request.QuizInfoModifyRequest;

//TODO: quizDescription 넣어야 될지 얘기해보기

Expand Down Expand Up @@ -44,8 +43,8 @@ public QuizInfo(QuizContent quizContent, Byte answerNum, String quizImage) {
this.quizImage = quizImage;
}

public void update(QuizInfoModifyRequest quizInfoModifyRequest) {
this.answerNum = quizInfoModifyRequest.getAnswerNum();
this.quizImage = quizInfoModifyRequest.getQuizImage();
public void update(Byte answerNum, String quizImage) {
this.answerNum = answerNum;
this.quizImage = quizImage;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ public enum QuizErrorCode implements ErrorCode {
NO_QUIZ_CONTENT(HttpStatus.BAD_REQUEST, "퀴즈 내용이 존재하지 않습니다."),
PARTICIPATION_EXISTS(HttpStatus.FORBIDDEN, "이미 참여한 유저입니다."),
ALREADY_WIN_REWARD_TODAY(HttpStatus.BAD_REQUEST, "이미 오늘 선착순 경품을 수령한 유저입니다."),
NO_QUIZ_REWARD(HttpStatus.BAD_REQUEST, "선착순 경품이 존재하지 않습니다.");
NO_QUIZ_REWARD(HttpStatus.BAD_REQUEST, "선착순 경품이 존재하지 않습니다."),
NO_QUIZ_IMAGE(HttpStatus.BAD_REQUEST, "퀴즈 정답 이미지가 존재하지 않습니다.");

private final HttpStatus httpStatus;
private final String message;
Expand Down
Loading

0 comments on commit 0a8e91b

Please sign in to comment.