Skip to content

Commit

Permalink
feat: 스터디 V2 팩토리 구현 (#855)
Browse files Browse the repository at this point in the history
* feat: 스터디회차에 회차 순서 추가

* feat: 빈 스터디회차를 생성하는 정팩메로 변경

* feat: 출석번호 생성기 인터페이스 및 구현체 추가

* feat: 스터디 팩토리 구현

* refactor: 매직넘버 상수로 추출

* feat: 학기 VO에 정팩메 추가

* feat: V2 전용 상수 추가

* test: 스터디 팩토리 테스트 추가
  • Loading branch information
uwoobeat authored Jan 30, 2025
1 parent 3f5ea6e commit 64acab1
Show file tree
Hide file tree
Showing 7 changed files with 221 additions and 13 deletions.
14 changes: 14 additions & 0 deletions src/main/java/com/gdschongik/gdsc/domain/common/vo/Semester.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -19,4 +20,17 @@ public class Semester {

@Enumerated(EnumType.STRING)
private SemesterType semesterType;

@Builder(access = AccessLevel.PRIVATE)
private Semester(int academicYear, SemesterType semesterType) {
this.academicYear = academicYear;
this.semesterType = semesterType;
}

public static Semester of(int academicYear, SemesterType semesterType) {
return Semester.builder()
.academicYear(academicYear)
.semesterType(semesterType)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.gdschongik.gdsc.domain.studyv2.domain;

public interface AttendanceNumberGenerator {
int generate();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.gdschongik.gdsc.domain.studyv2.domain;

import java.security.SecureRandom;
import lombok.SneakyThrows;

/**
* 네 자리의 랜덤한 출석번호를 생성합니다.
*/
public class RandomAttendanceNumberGenerator implements AttendanceNumberGenerator {

public static final int MIN_ORIGIN = 1000;
public static final int MAX_BOUND = 10000;

@Override
@SneakyThrows
public int generate() {
return SecureRandom.getInstanceStrong()
.ints(MIN_ORIGIN, MAX_BOUND)
.findFirst()
.orElseThrow();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.gdschongik.gdsc.domain.studyv2.domain;

import com.gdschongik.gdsc.domain.common.vo.Period;
import com.gdschongik.gdsc.domain.common.vo.Semester;
import com.gdschongik.gdsc.domain.member.domain.Member;
import com.gdschongik.gdsc.domain.study.domain.StudyType;
import com.gdschongik.gdsc.global.annotation.DomainFactory;
import java.time.DayOfWeek;
import java.time.LocalTime;
import java.util.stream.IntStream;

@DomainFactory
public class StudyFactory {

/**
* 스터디 및 스터디회차를 생성합니다.
* 스터디회차의 경우 총 회차 수만큼 생성되며, 생성 순서에 따라 position 값이 지정됩니다.
*/
public StudyV2 create(
StudyType type,
String title,
String description,
String descriptionNotionLink,
Semester semester,
Integer totalRound,
DayOfWeek dayOfWeek,
LocalTime startTime,
LocalTime endTime,
Period applicationPeriod,
String discordChannelId,
String discordRoleId,
Member mentor,
AttendanceNumberGenerator attendanceNumberGenerator) {
StudyV2 study = StudyV2.create(
type,
title,
description,
descriptionNotionLink,
semester,
totalRound,
dayOfWeek,
startTime,
endTime,
applicationPeriod,
discordChannelId,
discordRoleId,
mentor);

IntStream.rangeClosed(1, totalRound)
.forEach(round -> StudySessionV2.createEmpty(round, attendanceNumberGenerator.generate(), study));

return study;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public class StudySessionV2 extends BaseEntity {
@Column(name = "study_session_v2_id")
private Long id;

@Comment("회차 순서")
private Integer position;

@Comment("회차 제목")
private String title;

Expand Down Expand Up @@ -70,13 +73,15 @@ public class StudySessionV2 extends BaseEntity {
*/
@Builder(access = AccessLevel.PRIVATE)
private StudySessionV2(
Integer position,
String title,
String description,
Integer lessonAttendanceNumber,
Period lessonPeriod,
String assignmentDescriptionLink,
Period assignmentPeriod,
StudyV2 studyV2) {
this.position = position;
this.title = title;
this.description = description;
this.lessonAttendanceNumber = lessonAttendanceNumber;
Expand All @@ -87,21 +92,10 @@ private StudySessionV2(
studyV2.getStudySessions().add(this);
}

public static void create(
String title,
String description,
Integer lessonAttendanceNumber,
Period lessonPeriod,
String assignmentDescriptionLink,
Period assignmentPeriod,
StudyV2 studyV2) {
public static void createEmpty(Integer position, Integer lessonAttendanceNumber, StudyV2 studyV2) {
StudySessionV2.builder()
.title(title)
.description(description)
.position(position)
.lessonAttendanceNumber(lessonAttendanceNumber)
.lessonPeriod(lessonPeriod)
.assignmentDescriptionLink(assignmentDescriptionLink)
.assignmentPeriod(assignmentPeriod)
.studyV2(studyV2)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.gdschongik.gdsc.domain.studyv2.domain;

import static com.gdschongik.gdsc.global.common.constant.StudyConstant.*;
import static org.assertj.core.api.Assertions.*;

import com.gdschongik.gdsc.domain.member.domain.Member;
import com.gdschongik.gdsc.domain.study.domain.StudyType;
import com.gdschongik.gdsc.helper.FixtureHelper;
import org.junit.jupiter.api.Test;

class StudyFactoryTest {

FixtureHelper fixtureHelper = new FixtureHelper();
StudyFactory studyFactory = new StudyFactory();

static class FixedAttendanceNumberGenerator implements AttendanceNumberGenerator {
@Override
public int generate() {
return 1000;
}
}

@Test
void 스터디_생성시_설정한_총_회차만큼_스터디회차가_생성된다() {
// given
Member mentor = fixtureHelper.createMentor(1L);
AttendanceNumberGenerator generator = new FixedAttendanceNumberGenerator();
int totalRound = 8;

// when
StudyV2 study = studyFactory.create(
StudyType.OFFLINE,
STUDY_TITLE,
STUDY_DESCRIPTION,
STUDY_DESCRIPTION_NOTION_LINK,
STUDY_SEMESTER,
totalRound,
DAY_OF_WEEK,
STUDY_START_TIME,
STUDY_END_TIME,
STUDY_APPLICATION_PERIOD,
STUDY_DISCORD_CHANNEL_ID,
STUDY_DISCORD_ROLE_ID,
mentor,
generator);

// then
assertThat(study.getStudySessions()).hasSize(8);
}

@Test
void 스터디_생성시_스터디회차는_순서대로_position이_지정되어_생성된다() {
// given
Member mentor = fixtureHelper.createMentor(1L);
AttendanceNumberGenerator generator = new FixedAttendanceNumberGenerator();
int totalRound = 8;

// when
StudyV2 study = studyFactory.create(
StudyType.OFFLINE,
STUDY_TITLE,
STUDY_DESCRIPTION,
STUDY_DESCRIPTION_NOTION_LINK,
STUDY_SEMESTER,
totalRound,
DAY_OF_WEEK,
STUDY_START_TIME,
STUDY_END_TIME,
STUDY_APPLICATION_PERIOD,
STUDY_DISCORD_CHANNEL_ID,
STUDY_DISCORD_ROLE_ID,
mentor,
generator);

// then
assertThat(study.getStudySessions())
.extracting(StudySessionV2::getPosition)
.containsExactly(1, 2, 3, 4, 5, 6, 7, 8);
}

@Test
void 스터디_생성시_각_스터디회차에_출석번호가_생성된다() {
// given
Member mentor = fixtureHelper.createMentor(1L);
AttendanceNumberGenerator generator = new FixedAttendanceNumberGenerator();

// when
StudyV2 study = studyFactory.create(
StudyType.OFFLINE,
STUDY_TITLE,
STUDY_DESCRIPTION,
STUDY_DESCRIPTION_NOTION_LINK,
STUDY_SEMESTER,
TOTAL_ROUND,
DAY_OF_WEEK,
STUDY_START_TIME,
STUDY_END_TIME,
STUDY_APPLICATION_PERIOD,
STUDY_DISCORD_CHANNEL_ID,
STUDY_DISCORD_ROLE_ID,
mentor,
generator);

// then
assertThat(study.getStudySessions())
.extracting(StudySessionV2::getLessonAttendanceNumber)
.containsOnly(1000);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.gdschongik.gdsc.global.common.constant;

import com.gdschongik.gdsc.domain.common.model.SemesterType;
import com.gdschongik.gdsc.domain.common.vo.Period;
import com.gdschongik.gdsc.domain.common.vo.Semester;
import com.gdschongik.gdsc.domain.study.domain.StudyType;
import java.time.DayOfWeek;
import java.time.LocalDateTime;
Expand All @@ -10,12 +12,20 @@ public class StudyConstant {
private StudyConstant() {}

public static final String STUDY_TITLE = "스터디 제목";
public static final String STUDY_DESCRIPTION = "스터디 설명";
public static final String STUDY_DESCRIPTION_NOTION_LINK = "https://gdschongik.com/2025-1-backend-study";
public static final Semester STUDY_SEMESTER = Semester.of(2025, SemesterType.FIRST);
public static final Long TOTAL_WEEK = 8L;
public static final int TOTAL_ROUND = 8;
public static final StudyType ONLINE_STUDY = StudyType.ONLINE;
public static final StudyType ASSIGNMENT_STUDY = StudyType.ASSIGNMENT;
public static final DayOfWeek DAY_OF_WEEK = DayOfWeek.FRIDAY;
public static final LocalTime STUDY_START_TIME = LocalTime.of(19, 0, 0);
public static final LocalTime STUDY_END_TIME = LocalTime.of(20, 0, 0);
public static final Period STUDY_APPLICATION_PERIOD =
Period.of(LocalDateTime.of(2025, 3, 1, 0, 0), LocalDateTime.of(2025, 3, 14, 23, 59));
public static final String STUDY_DISCORD_CHANNEL_ID = "12345678";
public static final String STUDY_DISCORD_ROLE_ID = "12345678";

// StudyDetail
public static final String ATTENDANCE_NUMBER = "1234";
Expand Down

0 comments on commit 64acab1

Please sign in to comment.