Skip to content

Commit

Permalink
feat-be(dashboard): 특정 동아리의 대시보드(공고) 생성 API 구현 (#215)
Browse files Browse the repository at this point in the history
authored-by: Do Yeop Kim <113661364+Dobby-Kim@users.noreply.github.com>
  • Loading branch information
github-actions[bot] authored Aug 1, 2024
1 parent 8330765 commit ac97e15
Show file tree
Hide file tree
Showing 26 changed files with 560 additions and 80 deletions.
4 changes: 2 additions & 2 deletions backend/src/main/java/com/cruru/DataLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ private void runDataLoader() {
Question essayQuestion = questionRepository.save(
new Question(SHORT_ANSWER, "좋아하는 숫자가 무엇인가요?", 1, applyForm));

Choice maleChoice = choiceRepository.save(new Choice(1L, "남", choiceQuestion));
Choice femaleChoice = choiceRepository.save(new Choice(2L, "여", choiceQuestion));
Choice maleChoice = choiceRepository.save(new Choice(1L, "남", 1, choiceQuestion));
Choice femaleChoice = choiceRepository.save(new Choice(2L, "여", 2, choiceQuestion));

List<Answer> answers = List.of(
new Answer(1L, maleChoice.getContent(), choiceQuestion, lurgi),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.cruru.applyform.controller.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import java.time.LocalDateTime;

public record ApplyFormCreateRequest(
@NotBlank(message = "제목은 필수 값입니다.")
String title,

@JsonProperty("posting_content")
String postingContent,

@NotBlank(message = "시작 날짜는 필수 값입니다.")
LocalDateTime startDate,

@NotBlank(message = "종료 날짜는 필수 값입니다.")
LocalDateTime dueDate
) {

}
32 changes: 24 additions & 8 deletions backend/src/main/java/com/cruru/applyform/domain/ApplyForm.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
Expand All @@ -31,10 +32,11 @@ public class ApplyForm extends BaseEntity {

private String description;

@Setter
private String url;

@Column(name = "start_date")
private LocalDateTime startDate;
@Column(name = "open_date")
private LocalDateTime openDate;

@Column(name = "due_date")
private LocalDateTime dueDate;
Expand All @@ -47,14 +49,28 @@ public ApplyForm(
String title,
String description,
String url,
LocalDateTime startDate,
LocalDateTime openDate,
LocalDateTime dueDate,
Dashboard dashboard
) {
this.title = title;
this.description = description;
this.url = url;
this.startDate = startDate;
this.openDate = openDate;
this.dueDate = dueDate;
this.dashboard = dashboard;
}

public ApplyForm(
String title,
String description,
LocalDateTime openDate,
LocalDateTime dueDate,
Dashboard dashboard
) {
this.title = title;
this.description = description;
this.openDate = openDate;
this.dueDate = dueDate;
this.dashboard = dashboard;
}
Expand All @@ -78,13 +94,13 @@ public int hashCode() {
@Override
public String toString() {
return "ApplyForm{" +
"id=" + id +
"dashboard=" + dashboard +
", id=" + id +
", title='" + title + '\'' +
", description='" + description + '\'' +
", url='" + url + '\'' +
", dashboard=" + dashboard +
", startDate=" + startDate +
", openDate=" + openDate +
", dueDate=" + dueDate +
", description='" + description + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package com.cruru.applyform.service;


import com.cruru.advice.InternalServerException;
import com.cruru.answer.domain.Answer;
import com.cruru.answer.domain.repository.AnswerRepository;
import com.cruru.applicant.domain.Applicant;
import com.cruru.applicant.domain.repository.ApplicantRepository;
import com.cruru.applyform.controller.dto.AnswerCreateRequest;
import com.cruru.applyform.controller.dto.ApplyFormCreateRequest;
import com.cruru.applyform.controller.dto.ApplyFormSubmitRequest;
import com.cruru.applyform.domain.ApplyForm;
import com.cruru.applyform.domain.repository.ApplyFormRepository;
import com.cruru.applyform.exception.ApplyFormNotFoundException;
import com.cruru.applyform.exception.PersonalDataProcessingException;
import com.cruru.dashboard.domain.Dashboard;
import com.cruru.process.domain.Process;
import com.cruru.process.domain.repository.ProcessRepository;
import com.cruru.question.domain.Question;
Expand All @@ -26,13 +27,36 @@
@RequiredArgsConstructor
public class ApplyFormService {

private static final String APPLY_FORM_BASE_URL = "www.cruru.kr/applyform/";

private final ApplicantRepository applicantRepository;
private final AnswerRepository answerRepository;
private final QuestionRepository questionRepository;
private final ApplyFormRepository applyFormRepository;
private final ProcessRepository processRepository;

@Transactional
public ApplyForm create(ApplyFormCreateRequest request, Dashboard createdDashboard) {
ApplyForm applyForm = toApplyForm(request, createdDashboard);

ApplyForm savedApplyForm = applyFormRepository.save(applyForm);
Long savedId = savedApplyForm.getId();
String generatedUrl = APPLY_FORM_BASE_URL + savedId;
savedApplyForm.setUrl(generatedUrl);

return savedApplyForm;
}

private ApplyForm toApplyForm(ApplyFormCreateRequest request, Dashboard createdDashboard) {
return new ApplyForm(
request.title(),
request.postingContent(),
request.startDate(),
request.dueDate(),
createdDashboard
);
}

public void submit(ApplyFormSubmitRequest request, long applyFormId) {
validatePersonalDataCollection(request);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.cruru.choice.controller.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;

public record ChoiceCreateRequest(
@NotBlank(message = "객관식 질문의 선택지는 필수 값입니다.")
String choice,

@JsonProperty("order_index")
int orderIndex
) {

}
5 changes: 4 additions & 1 deletion backend/src/main/java/com/cruru/choice/domain/Choice.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,15 @@ public class Choice {

private String content;

private Integer sequence;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "question_id")
private Question question;

public Choice(String content, Question question) {
public Choice(String content, Integer sequence, Question question) {
this.content = content;
this.sequence = sequence;
this.question = question;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.cruru.choice.exception;

import com.cruru.advice.badrequest.BadRequestException;

public class ChoiceEmptyBadRequestException extends BadRequestException {

private static final String MESSAGE = "객관식 질문에는 1개 이상의 객관식 선택지를 포함해야합니다.";

public ChoiceEmptyBadRequestException() {
super(MESSAGE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.cruru.choice.exception;

import com.cruru.advice.badrequest.BadRequestException;

public class ChoiceIllegalSaveException extends BadRequestException {

private static final String MESSAGE = "선택지를 저장할 수 없는 질문입니다.";

public ChoiceIllegalSaveException() {
super(MESSAGE);
}
}
43 changes: 43 additions & 0 deletions backend/src/main/java/com/cruru/choice/service/ChoiceService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.cruru.choice.service;

import com.cruru.choice.controller.dto.ChoiceCreateRequest;
import com.cruru.choice.domain.Choice;
import com.cruru.choice.domain.repository.ChoiceRepository;
import com.cruru.choice.exception.ChoiceEmptyBadRequestException;
import com.cruru.choice.exception.ChoiceIllegalSaveException;
import com.cruru.question.domain.Question;
import com.cruru.question.domain.repository.QuestionRepository;
import com.cruru.question.exception.QuestionNotFoundException;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class ChoiceService {

private final ChoiceRepository choiceRepository;
private final QuestionRepository questionRepository;

@Transactional
public List<Choice> createAll(List<ChoiceCreateRequest> requests, long questionId) {
Question targetQuestion = questionRepository.findById(questionId)
.orElseThrow(QuestionNotFoundException::new);

if (!targetQuestion.hasChoice()) {
throw new ChoiceIllegalSaveException();
}
if (requests.isEmpty()) {
throw new ChoiceEmptyBadRequestException();
}
return choiceRepository.saveAll(toChoices(requests, targetQuestion));
}

private List<Choice> toChoices(List<ChoiceCreateRequest> requests, Question question) {
return requests.stream()
.map(request -> new Choice(request.choice(), request.orderIndex(), question))
.toList();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.cruru.dashboard.controller;

import com.cruru.dashboard.controller.dto.DashboardCreateRequest;
import com.cruru.dashboard.service.DashboardService;
import com.cruru.dashboard.service.facade.DashboardFacade;
import jakarta.validation.Valid;
import java.net.URI;
import lombok.RequiredArgsConstructor;
Expand All @@ -17,13 +17,14 @@
@RequiredArgsConstructor
public class DashboardController {

private final DashboardService dashboardService;
private final DashboardFacade dashboardFacade;

@PostMapping
public ResponseEntity<Void> create(
@RequestParam(name = "club_id") Long clubId,
@RequestBody @Valid DashboardCreateRequest request) {
long dashboardId = dashboardService.create(clubId, request);

long dashboardId = dashboardFacade.create(clubId, request);
return ResponseEntity.created(URI.create("/v1/dashboards/" + dashboardId)).build();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,32 @@
package com.cruru.dashboard.controller.dto;

import com.cruru.question.controller.dto.QuestionCreateRequest;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.List;

public record DashboardCreateRequest(
@NotBlank(message = "대시보드 이름은 필수 값입니다.")
String name
@NotBlank(message = "공고 제목은 필수 값입니다.")
String title,

@JsonProperty("posting_content")
String postingContent,

List<QuestionCreateRequest> questions,

@NotNull(message = "시작 날짜는 필수 값입니다.")
@JsonFormat(shape = Shape.STRING)
@JsonProperty("start_date")
LocalDateTime startDate,

@NotNull(message = "종료 날짜는 필수 값입니다.")
@JsonFormat(shape = Shape.STRING)
@JsonProperty("due_date")
LocalDateTime dueDate
) {

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import com.cruru.club.domain.Club;
import com.cruru.club.domain.repository.ClubRepository;
import com.cruru.club.exception.ClubNotFoundException;
import com.cruru.dashboard.controller.dto.DashboardCreateRequest;
import com.cruru.dashboard.domain.Dashboard;
import com.cruru.dashboard.domain.repository.DashboardRepository;
import com.cruru.process.domain.Process;
import com.cruru.process.domain.ProcessFactory;
import com.cruru.process.domain.repository.ProcessRepository;
import java.util.List;
import lombok.RequiredArgsConstructor;
Expand All @@ -18,33 +18,21 @@
@RequiredArgsConstructor
public class DashboardService {

private static final Process DEFAULT_FIRST_PROCESS = new Process(1, "지원 접수", "지원자가 지원서를 제출하는 단계", null);
private static final Process DEFAULT_LAST_PROCESS = new Process(2, "합격", "지원자가 최종적으로 합격한 단계", null);

private final DashboardRepository dashboardRepository;
private final ClubRepository clubRepository;
private final ProcessRepository processRepository;

@Transactional
public long create(long clubId, DashboardCreateRequest request) {
public Dashboard create(long clubId) {
Club club = clubRepository.findById(clubId)
.orElseThrow(ClubNotFoundException::new);
Dashboard savedDashboard = dashboardRepository.save(new Dashboard(club));

Process firstProcess = new Process(
DEFAULT_FIRST_PROCESS.getSequence(),
DEFAULT_FIRST_PROCESS.getName(),
DEFAULT_FIRST_PROCESS.getDescription(),
savedDashboard
);
Process lastProcess = new Process(
DEFAULT_LAST_PROCESS.getSequence(),
DEFAULT_LAST_PROCESS.getName(),
DEFAULT_LAST_PROCESS.getDescription(),
savedDashboard
);
Process firstProcess = ProcessFactory.createFirstOf(savedDashboard);
Process lastProcess = ProcessFactory.createLastOf(savedDashboard);

processRepository.saveAll(List.of(firstProcess, lastProcess));
return savedDashboard.getId();

return savedDashboard;
}
}
Loading

0 comments on commit ac97e15

Please sign in to comment.