Skip to content

Commit

Permalink
Merge pull request #30 from Central-MakeUs/feature/9
Browse files Browse the repository at this point in the history
Feature/9: Survey 관련 API 개발
  • Loading branch information
yxhwxn authored Aug 8, 2024
2 parents 2b48c40 + 19ae2da commit 322ded8
Show file tree
Hide file tree
Showing 31 changed files with 947 additions and 15 deletions.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.cmc.suppin.event.survey.controller;

import com.cmc.suppin.event.survey.controller.dto.SurveyRequestDTO;
import com.cmc.suppin.event.survey.controller.dto.SurveyResponseDTO;
import com.cmc.suppin.event.survey.service.SurveyService;
import com.cmc.suppin.global.response.ApiResponse;
import com.cmc.suppin.global.response.ResponseCode;
import com.cmc.suppin.global.security.reslover.Account;
import com.cmc.suppin.global.security.reslover.CurrentAccount;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@Slf4j
@RequiredArgsConstructor
@Validated
@Tag(name = "Event-Survey", description = "Survey 관련 API")
@RequestMapping("/api/v1/survey")
public class SurveyApi {

private final SurveyService surveyService;

@PostMapping("/create")
@Operation(summary = "설문지 생성 API", description = "QuestionType(Enum): SUBJECTIVE(주관식), SINGLE_CHOICE(객관식(단일 선택)), MULTIPLE_CHOICE(객관식(복수 선택))")
public ResponseEntity<ApiResponse<SurveyResponseDTO.SurveyCreateResponse>> createSurvey(@RequestBody @Valid SurveyRequestDTO.SurveyCreateDTO request, @CurrentAccount Account account) {
SurveyResponseDTO.SurveyCreateResponse response = surveyService.createSurvey(request, account.userId());
return ResponseEntity.ok(ApiResponse.of(response));
}

@GetMapping("/{surveyId}")
@Operation(summary = "설문지 조회 API", description = "Request: 설문지 ID, Response: 설문지 정보 <br><br>" +
"SUBJEVTIVE: 주관식, SINGLE_CHOICE: 객관식(단일 선택), MULTIPLE_CHOICE: 객관식(복수 선택)")
public ResponseEntity<ApiResponse<SurveyResponseDTO.SurveyResultDTO>> getSurvey(@PathVariable Long surveyId) {
SurveyResponseDTO.SurveyResultDTO response = surveyService.getSurvey(surveyId);
return ResponseEntity.ok(ApiResponse.of(response));
}

@PostMapping("/reply")
@Operation(summary = "설문 답변 등록 API")
public ResponseEntity<ApiResponse<Void>> saveSurveyAnswers(@RequestBody @Valid SurveyRequestDTO.SurveyAnswerDTO request) {
surveyService.saveSurveyAnswers(request);
return ResponseEntity.ok(ApiResponse.of(ResponseCode.SUCCESS));
}

@GetMapping("/{surveyId}/answers/{questionId}")
@Operation(summary = "질문별 설문 응답 결과 조회 API", description = "Request: 설문지 ID와 질문 ID, Response: 해당 질문에 대한 응답 리스트")
public ResponseEntity<ApiResponse<SurveyResponseDTO.SurveyAnswerResultDTO>> getSurveyAnswers(
@PathVariable Long surveyId,
@PathVariable Long questionId,
@RequestParam int page,
@RequestParam int size,
@CurrentAccount Account account) {
SurveyResponseDTO.SurveyAnswerResultDTO response = surveyService.getSurveyAnswers(surveyId, questionId, page, size, account.userId());
return ResponseEntity.ok(ApiResponse.of(response));
}

@PostMapping("/draft")
@Operation(summary = "당첨자 랜덤 추첨 결과 리스트 조회 API(설문 이벤트)", description = "주관식 답변 중 조건을 설정하여 랜덤으로 당첨자를 추첨합니다.")
public ResponseEntity<ApiResponse<SurveyResponseDTO.RandomSelectionResponseDTO>> selectRandomWinners(
@RequestBody @Valid SurveyRequestDTO.RandomSelectionRequestDTO request, @CurrentAccount Account account) {
SurveyResponseDTO.RandomSelectionResponseDTO response = surveyService.selectRandomWinners(request, account.userId());
return ResponseEntity.ok(ApiResponse.of(response));
}

// 당첨자 세부 정보 조회 API
@GetMapping("/winners/{surveyId}/{participantId}")
@Operation(summary = "당첨자 세부 정보 조회 API", description = "설문 이벤트의 당첨자(익명 참여자) 정보를 조회하며, 해당 참여자가 응답한 모든 설문 내용을 반환합니다.")
public ResponseEntity<ApiResponse<SurveyResponseDTO.WinnerDetailDTO>> getWinnerDetails(
@PathVariable Long surveyId, @PathVariable Long participantId) {
SurveyResponseDTO.WinnerDetailDTO winnerDetails = surveyService.getWinnerDetails(surveyId, participantId);
return ResponseEntity.ok(ApiResponse.of(winnerDetails));
}

@DeleteMapping("/winners")
@Operation(summary = "당첨자 리스트 삭제 API", description = "해당 설문조사의 모든 당첨자들의 isWinner 값을 false로 변경합니다.")
public ResponseEntity<ApiResponse<Void>> deleteWinners(@RequestParam Long surveyId) {
surveyService.deleteWinners(surveyId);
return ResponseEntity.ok(ApiResponse.of(ResponseCode.SUCCESS));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package com.cmc.suppin.event.survey.controller.dto;

import com.cmc.suppin.global.enums.QuestionType;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;

public class SurveyRequestDTO {

// 설문 생성 요청 DTO
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class SurveyCreateDTO {
@NotNull
private Long eventId;
private List<PersonalInfoOptionDTO> personalInfoOptionList;
private List<QuestionDTO> questionList;

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class QuestionDTO {
@NotBlank(message = "질문 유형: SUBJECTIVE(주관식), SINGLE_CHOICE(객관식(단일 선택)), MULTIPLE_CHOICE(객관식(복수 선택))")
private QuestionType questionType;
@NotBlank(message = "질문 내용을 입력해주세요")
private String questionText;
private List<String> options; // 객관식 질문일 경우 선택지 리스트
}

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class PersonalInfoOptionDTO {
@NotBlank(message = "개인정보 수집 항목을 입력해주세요")
private String optionName;
}
}

// 설문 답변 요청 DTO
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class SurveyAnswerDTO {
@NotNull
private Long surveyId;
@Valid
private ParticipantDTO participant;
@Valid
private List<AnswerDTO> answers;

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class ParticipantDTO {
private String name;
private String address;
private String email;
private String phoneNumber;
private String instagramId;
@NotNull
private Boolean isAgreed;
}

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class AnswerDTO {
@NotNull
private Long questionId;
private String answerText;
private List<AnswerOptionDTO> answerOptions;

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class AnswerOptionDTO {
@NotNull
private Long questionOptionId;
}
}
}

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class RandomSelectionRequestDTO {
@NotNull
private Long surveyId;
@NotNull
private Long questionId;
@NotNull
private Integer winnerCount;
@NotNull
private LocalDateTime startDate;
@NotNull
private LocalDateTime endDate;
@NotNull
private Integer minLength;
@NotNull
private List<String> keywords;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package com.cmc.suppin.event.survey.controller.dto;

import com.cmc.suppin.global.enums.QuestionType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;

public class SurveyResponseDTO {

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class SurveyCreateResponse {
private Long surveyId;
private String uuid;
}

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class SurveyResultDTO {
private Long eventId;
private String eventTitle;
private String eventDescription;
private String startDate;
private String endDate;
private String announcementDate;
private List<PersonalInfoOptionDTO> personalInfoOptions;
private List<QuestionDTO> questions;

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class QuestionDTO {
private QuestionType questionType;
private String questionText;
private List<String> options;
}

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class PersonalInfoOptionDTO {
private String optionName;
}
}

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class SurveyAnswerResultDTO {
private Long questionId;
private String questionText;
private List<AnswerDTO> answers;
private int totalPages;
private long totalElements;

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class AnswerDTO {
private String participantName;
private String answerText;
private List<String> selectedOptions;
}
}

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class RandomSelectionResponseDTO {
private SelectionCriteriaDTO selectionCriteria;
private List<WinnerDTO> winners;

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class WinnerDTO {
private Long participantId;
private String participantName;
private String answerText;
}

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class SelectionCriteriaDTO {
private Integer winnerCount;
private LocalDateTime startDate;
private LocalDateTime endDate;
private Integer minLength;
private List<String> keywords;
}
}

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class WinnerDetailDTO {
private String name;
private String phoneNumber;
private String address;
private String email;
private String instagramId;
private List<AnswerDetailDTO> answers;

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public static class AnswerDetailDTO {
private String questionText;
private String answerText;
private List<String> selectedOptions; // 객관식 질문의 경우 선택된 옵션 리스트
}
}
}
Empty file.
Loading

0 comments on commit 322ded8

Please sign in to comment.