Skip to content

Commit

Permalink
Merge pull request #17 from dnd-side-project/feature/#16-create-revie…
Browse files Browse the repository at this point in the history
…wform

[Feature] 리뷰 생성하기
  • Loading branch information
heejjinkim authored Oct 8, 2024
2 parents 5b23f8e + ab6414e commit 99a4418
Show file tree
Hide file tree
Showing 34 changed files with 1,014 additions and 462 deletions.
7 changes: 7 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,11 @@ jar {
}
clean {
delete file('src/main/generated')
}

test {
testLogging {
events "failed"
exceptionFormat "full"
}
}
64 changes: 28 additions & 36 deletions src/main/java/com/_119/wepro/global/config/DataInitializer.java
Original file line number Diff line number Diff line change
@@ -1,96 +1,88 @@
package com._119.wepro.global.config;

import com._119.wepro.global.enums.CategoryType;
import com._119.wepro.review.domain.ChoiceOption;
import com._119.wepro.review.domain.Option;
import com._119.wepro.review.domain.Question;
import com._119.wepro.review.domain.repository.ChoiceOptionCustomRepository;
import com._119.wepro.review.domain.repository.ChoiceOptionJdbcRepository;
import com._119.wepro.review.domain.repository.QuestionCustomRepository;
import com._119.wepro.review.domain.repository.QuestionJdbcRepository;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

@Slf4j
@Component
@RequiredArgsConstructor
public class DataInitializer implements ApplicationRunner {

private final ChoiceOptionJdbcRepository choiceOptionJdbcRepository;
private final ChoiceOptionCustomRepository choiceOptionCustomRepository;
private final QuestionJdbcRepository questionJdbcRepository;
private final QuestionCustomRepository questionCustomRepository;

private final ObjectMapper objectMapper;
private final AtomicLong questionIdCounter = new AtomicLong(1);
private final AtomicLong optionIdCounter = new AtomicLong(1);

@Override
public void run(ApplicationArguments args) throws Exception {

setDefaultQuestionsAndChoiceOption();
setDefaultQuestionsAndOptions();
}

private void setDefaultQuestionsAndChoiceOption() {

// DB에 데이터 없는 경우만 새로 생성
if (!questionCustomRepository.exists() && !choiceOptionCustomRepository.exists()) {
private void setDefaultQuestionsAndOptions() {
// DB에 데이터가 없는 경우만 새로 생성
if (!questionCustomRepository.exists()) {

List<Question> allQuestions = new ArrayList<>();
List<ChoiceOption> allChoiceOptions = new ArrayList<>();
List<CategoryQuestions> categoryQuestionsList;

// json 파일 읽기
// JSON 파일 읽기
try {
ClassPathResource resource = new ClassPathResource("default-questions.json");
categoryQuestionsList = objectMapper.readValue(
resource.getInputStream(), new TypeReference<List<CategoryQuestions>>() {
});
resource.getInputStream(), new TypeReference<List<CategoryQuestions>>() {});
} catch (IOException e) {
e.printStackTrace();
return;
}

// CategoryQuestions -> Question, ChoiceOption
// CategoryQuestions -> Question, Option
categoryQuestionsList.forEach(categoryQuestions -> {
CategoryType categoryType = categoryQuestions.categoryType();
categoryQuestions.questions().forEach(questionWithOptions -> {
Question question = Question.of(questionIdCounter.getAndIncrement(), categoryType,
questionWithOptions.question());
List<ChoiceOption> options = createOptionsForQuestion(question,
questionWithOptions.options());

Question question = Question.builder()
.content(questionWithOptions.question())
.categoryType(categoryType)
.options(createOptionsForQuestion(questionWithOptions.options()))
.build();

allQuestions.add(question);
allChoiceOptions.addAll(options);
});
});

questionJdbcRepository.batchInsert(allQuestions);
choiceOptionJdbcRepository.batchInsert(allChoiceOptions);
}
}

private List<ChoiceOption> createOptionsForQuestion(Question question, List<String> optionTexts) {
List<ChoiceOption> options = new ArrayList<>();
private List<Option> createOptionsForQuestion(List<String> optionTexts) {
List<Option> options = new ArrayList<>();
for (int i = 0; i < optionTexts.size(); i++) {
options.add(ChoiceOption.of(i + 1, optionTexts.get(i), question));
options.add(Option.builder()
.id(optionIdCounter.getAndIncrement())
.content(optionTexts.get(i))
.build());
}
return options;
}

private record CategoryQuestions(CategoryType categoryType, List<QuestionWithOptions> questions) {
private record CategoryQuestions(CategoryType categoryType, List<QuestionWithOptions> questions) {}

}

private record QuestionWithOptions(String question, List<String> options) {

}
private record QuestionWithOptions(String question, List<String> options) {}
}
7 changes: 4 additions & 3 deletions src/main/java/com/_119/wepro/global/enums/CategoryType.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
public enum CategoryType {
COMMUNICATION("커뮤니케이션"),
SKILL("기술"),
COLLABORATION("협업"),
LEADERSHIP("리더십"),
FOLLOWERSHIP("팔로워십"),
DOCUMENTATION("문서화"),
TIME_MANAGEMENT("시간관리"),
PROBLEM_SOLVING("문제해결"),
DILIGENCE("성실성");
DILIGENCE("성실성"),
IDEATION("아이데이션"),
SOCIABILITY("사회성");

private final String name;
}
17 changes: 0 additions & 17 deletions src/main/java/com/_119/wepro/global/enums/Provider.java

This file was deleted.

5 changes: 0 additions & 5 deletions src/main/java/com/_119/wepro/global/enums/Role.java

This file was deleted.

5 changes: 0 additions & 5 deletions src/main/java/com/_119/wepro/global/enums/Status.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ public enum ReviewErrorCode implements ErrorCode {
OPTION_NOT_FOUND(HttpStatus.NOT_FOUND, "Option not found"),
QUESTION_NOT_FOUND(HttpStatus.NOT_FOUND, "Question not found"),
CATEGORY_NOT_FOUND(HttpStatus.NOT_FOUND, "Category not found"),
QUESTIONS_NOT_FOUND_FOR_CATEGORY(HttpStatus.NOT_FOUND, "No questions found for the given category")
QUESTIONS_NOT_FOUND_FOR_CATEGORY(HttpStatus.NOT_FOUND, "No questions found for the given category"),
REVIEW_FORM_NOT_FOUND(HttpStatus.NOT_FOUND, "Review Form not found")
;

private final HttpStatus httpStatus;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo
CustomOidcUser user = (CustomOidcUser) authentication.getPrincipal();

// 토큰 발급
TokenInfo tokenInfo = jwtTokenProvider.generateToken(user.getAttribute("sub"),
TokenInfo tokenInfo = jwtTokenProvider.generateToken(String.valueOf(user.getMemberId()),
user.getMemberRole());

response.sendRedirect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
@Component
public class JwtTokenProvider {

private static final long ACCESS_TOKEN_DURATION = 1000 * 60 * 60L * 24; // 1일
private static final long ACCESS_TOKEN_DURATION = 1000 * 60 * 60L * 24 * 7; // TODO: 임시 7일
private static final long REFRESH_TOKEN_DURATION = 1000 * 60 * 60L * 24 * 7; // 7일

private final RedisUtil redisUtil;
Expand All @@ -44,12 +44,12 @@ public JwtTokenProvider(@Value("${jwt.secret}") String key, RedisUtil redisUtil)
this.secretKey = Keys.hmacShaKeyFor(key.getBytes());
}

public TokenInfo generateToken(String providerId, MemberRole memberRole) {
String accessToken = generateAccessToken(providerId, memberRole);
public TokenInfo generateToken(String memberId, MemberRole memberRole) {
String accessToken = generateAccessToken(memberId, memberRole);
String refreshToken = generateRefreshToken();

deleteInvalidRefreshToken(providerId);
redisUtil.setData(providerId, refreshToken);
deleteInvalidRefreshToken(memberId);
redisUtil.setData(memberId, refreshToken);

return new TokenInfo(GRANT_TYPE, accessToken, refreshToken);
}
Expand Down Expand Up @@ -104,12 +104,12 @@ private Claims parseClaims(String accessToken) {
}
}

private String generateAccessToken(String providerId, MemberRole memberRole) {
private String generateAccessToken(String memberId, MemberRole memberRole) {
Date now = new Date();
Date expiredDate = new Date(now.getTime() + ACCESS_TOKEN_DURATION);

return Jwts.builder()
.setSubject(providerId)
.setSubject(memberId)
.claim(AUTHORITIES_KEY, memberRole.name())
.setIssuedAt(now)
.setExpiration(expiredDate)
Expand Down
1 change: 0 additions & 1 deletion src/main/java/com/_119/wepro/global/util/SecurityUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ public class SecurityUtil {
public Long getCurrentMemberId() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
try {
// Todo : getName = provider Id이므로 수정할 것
return Long.parseLong(authentication.getName());
} catch (Exception e) {
throw new RestApiException(USER_NOT_FOUND);
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/_119/wepro/project/domain/Project.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,25 @@
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import java.util.List;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
@Entity
@Getter
public class Project extends BaseEntity {

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

@OneToMany(mappedBy = "project")
private List<ProjectMember> projectMembers;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com._119.wepro.review.domain;
package com._119.wepro.project.domain;

import com._119.wepro.global.BaseEntity;
import com._119.wepro.member.domain.Member;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
Expand All @@ -19,24 +20,17 @@
@Entity
@Getter
@Builder
public class ReviewFormQuestion extends BaseEntity {
public class ProjectMember extends BaseEntity {

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

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "review_form_id")
private ReviewForm reviewForm;
@JoinColumn(name = "member_id")
private Member member;

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

public static ReviewFormQuestion of(ReviewForm reviewForm, Question question) {
return ReviewFormQuestion.builder()
.reviewForm(reviewForm)
.question(question)
.build();
}
@JoinColumn(name = "project_id")
private Project project;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com._119.wepro.project.domain.repository;

import com._119.wepro.alarm.domain.QAlarm;
import com._119.wepro.global.enums.AlarmType;
import com._119.wepro.member.domain.QMember;
import com._119.wepro.project.domain.ProjectMember;
import com._119.wepro.project.domain.QProjectMember;
import com.querydsl.jpa.JPAExpressions;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

@RequiredArgsConstructor
@Repository
public class ProjectMemberCustomRepository {

private final JPAQueryFactory queryFactory;

public List<ProjectMember> getProjectMembersWithoutReviewRequest(Long reviewFormId) {
QProjectMember projectMember = QProjectMember.projectMember;
QAlarm alarm = QAlarm.alarm;
QMember member = QMember.member; // Member 엔티티를 가져오기 위해 추가

return queryFactory
.selectFrom(projectMember)
.join(projectMember.member, member).fetchJoin()
.where(projectMember.id.notIn(
JPAExpressions
.select(alarm.receiver.id)
.from(alarm)
.where(alarm.targetId.eq(reviewFormId)
.and(alarm.alarmType.eq(AlarmType.REVIEW_REQUEST)))
))
.fetch();
}
}
42 changes: 0 additions & 42 deletions src/main/java/com/_119/wepro/review/domain/ChoiceOption.java

This file was deleted.

Loading

0 comments on commit 99a4418

Please sign in to comment.