Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] 리뷰 생성하기 #17

Merged
merged 18 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading