From 96a1d78ce5c5b8528ccb96382dbffddf3361c42f Mon Sep 17 00:00:00 2001 From: yumble Date: Wed, 6 Dec 2023 10:31:57 +0900 Subject: [PATCH 01/14] rename: FileSize, FileDimensions => ThumbnailSize, ThumbnailDimensions --- src/main/java/nextstep/courses/domain/Thumbnail.java | 10 +++++----- .../{FileDimensions.java => ThumbnailDimensions.java} | 4 ++-- .../domain/{FileSize.java => ThumbnailSize.java} | 4 ++-- ...imensionsTest.java => ThumbnailDimensionsTest.java} | 8 ++++---- .../{FileSizeTest.java => ThumbnailSizeTest.java} | 4 ++-- .../java/nextstep/courses/domain/ThumbnailTest.java | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) rename src/main/java/nextstep/courses/domain/{FileDimensions.java => ThumbnailDimensions.java} (95%) rename src/main/java/nextstep/courses/domain/{FileSize.java => ThumbnailSize.java} (91%) rename src/test/java/nextstep/courses/domain/{FileDimensionsTest.java => ThumbnailDimensionsTest.java} (73%) rename src/test/java/nextstep/courses/domain/{FileSizeTest.java => ThumbnailSizeTest.java} (76%) diff --git a/src/main/java/nextstep/courses/domain/Thumbnail.java b/src/main/java/nextstep/courses/domain/Thumbnail.java index fd33abda1..c45b54092 100644 --- a/src/main/java/nextstep/courses/domain/Thumbnail.java +++ b/src/main/java/nextstep/courses/domain/Thumbnail.java @@ -8,17 +8,17 @@ public class Thumbnail { private static final Pattern IMAGE_EXTENSION_PATTERN = Pattern.compile(".*\\.(gif|jpe?g|png|svg)$", Pattern.CASE_INSENSITIVE); private final Integer thumbnailId; private final String thumbnailName; - private final FileSize thumbnailSize; - private final FileDimensions thumbnailDimensions; + private final ThumbnailSize thumbnailSize; + private final ThumbnailDimensions thumbnailDimensions; public Thumbnail(Integer thumbnailId, String thumbnailName, long thumbnailSize, int thumbnailWidth, int thumbnailHeight) { - this(thumbnailId, thumbnailName, new FileSize(thumbnailSize), - new FileDimensions(thumbnailWidth, thumbnailHeight)); + this(thumbnailId, thumbnailName, new ThumbnailSize(thumbnailSize), + new ThumbnailDimensions(thumbnailWidth, thumbnailHeight)); } public Thumbnail(Integer thumbnailId, String thumbnailName, - FileSize thumbnailSize, FileDimensions thumbnailDimensions) { + ThumbnailSize thumbnailSize, ThumbnailDimensions thumbnailDimensions) { validateThumbnailExt(thumbnailName); this.thumbnailId = thumbnailId; this.thumbnailName = thumbnailName; diff --git a/src/main/java/nextstep/courses/domain/FileDimensions.java b/src/main/java/nextstep/courses/domain/ThumbnailDimensions.java similarity index 95% rename from src/main/java/nextstep/courses/domain/FileDimensions.java rename to src/main/java/nextstep/courses/domain/ThumbnailDimensions.java index 1f7170ba8..97f877e51 100644 --- a/src/main/java/nextstep/courses/domain/FileDimensions.java +++ b/src/main/java/nextstep/courses/domain/ThumbnailDimensions.java @@ -2,7 +2,7 @@ import nextstep.courses.exception.FileException.FileDimensionsException; -public class FileDimensions { +public class ThumbnailDimensions { private static final int MIN_THUMBNAIL_FILE_LENGTH = 0; private static final int MAX_THUMBNAIL_FILE_WIDTH = 300; @@ -13,7 +13,7 @@ public class FileDimensions { private final int width; private final int height; - public FileDimensions(int width, int height) { + public ThumbnailDimensions(int width, int height) { validateFileDimensions(width, height); this.width = width; this.height = height; diff --git a/src/main/java/nextstep/courses/domain/FileSize.java b/src/main/java/nextstep/courses/domain/ThumbnailSize.java similarity index 91% rename from src/main/java/nextstep/courses/domain/FileSize.java rename to src/main/java/nextstep/courses/domain/ThumbnailSize.java index 7d6414355..187ad6ceb 100644 --- a/src/main/java/nextstep/courses/domain/FileSize.java +++ b/src/main/java/nextstep/courses/domain/ThumbnailSize.java @@ -2,14 +2,14 @@ import nextstep.courses.exception.FileException.FileSizeException; -public class FileSize { +public class ThumbnailSize { private static final long MAX_THUMBNAIL_FILE_SIZE = 1024L * 1024L; private static final long MIN_THUMBNAIL_FILE_SIZE = 0L; private final long size; - public FileSize(long size) { + public ThumbnailSize(long size) { validateFileSize(size); this.size = size; } diff --git a/src/test/java/nextstep/courses/domain/FileDimensionsTest.java b/src/test/java/nextstep/courses/domain/ThumbnailDimensionsTest.java similarity index 73% rename from src/test/java/nextstep/courses/domain/FileDimensionsTest.java rename to src/test/java/nextstep/courses/domain/ThumbnailDimensionsTest.java index c9ae435b7..84d536e02 100644 --- a/src/test/java/nextstep/courses/domain/FileDimensionsTest.java +++ b/src/test/java/nextstep/courses/domain/ThumbnailDimensionsTest.java @@ -5,23 +5,23 @@ import nextstep.courses.exception.FileException.FileDimensionsException; import org.junit.jupiter.api.Test; -public class FileDimensionsTest { +public class ThumbnailDimensionsTest { @Test public void 파일_너비_300픽셀_미만_시_에러_테스트() { - assertThatThrownBy(() -> new FileDimensions(299, 200)) + assertThatThrownBy(() -> new ThumbnailDimensions(299, 200)) .isInstanceOf(FileDimensionsException.class); } @Test public void 파일_높이_200픽셀_미만_시_에러_테스트() { - assertThatThrownBy(() -> new FileDimensions(300, 199)) + assertThatThrownBy(() -> new ThumbnailDimensions(300, 199)) .isInstanceOf(FileDimensionsException.class); } @Test public void 파일_너비_높이_비율_3_대_2_아닐_시_에러_테스트() { - assertThatThrownBy(() -> new FileDimensions(300, 300)) + assertThatThrownBy(() -> new ThumbnailDimensions(300, 300)) .isInstanceOf(FileDimensionsException.class); } } diff --git a/src/test/java/nextstep/courses/domain/FileSizeTest.java b/src/test/java/nextstep/courses/domain/ThumbnailSizeTest.java similarity index 76% rename from src/test/java/nextstep/courses/domain/FileSizeTest.java rename to src/test/java/nextstep/courses/domain/ThumbnailSizeTest.java index 51406cdc6..3e6d93391 100644 --- a/src/test/java/nextstep/courses/domain/FileSizeTest.java +++ b/src/test/java/nextstep/courses/domain/ThumbnailSizeTest.java @@ -5,11 +5,11 @@ import nextstep.courses.exception.FileException.FileSizeException; import org.junit.jupiter.api.Test; -public class FileSizeTest { +public class ThumbnailSizeTest { @Test public void 파일_크기_1MB_초과_시_에러_테스트() { - assertThatThrownBy(() -> new FileSize(1024L * 1024L + 1)) + assertThatThrownBy(() -> new ThumbnailSize(1024L * 1024L + 1)) .isInstanceOf(FileSizeException.class); } } diff --git a/src/test/java/nextstep/courses/domain/ThumbnailTest.java b/src/test/java/nextstep/courses/domain/ThumbnailTest.java index 6249e6369..6f9a34f43 100644 --- a/src/test/java/nextstep/courses/domain/ThumbnailTest.java +++ b/src/test/java/nextstep/courses/domain/ThumbnailTest.java @@ -10,7 +10,7 @@ public class ThumbnailTest { @Test public void 파일확장자_다른_것_사용_시_에러_테스트() { assertThatThrownBy(() -> new Thumbnail(1, "thumbnail.xlsx", - new FileSize(1024L * 1024L), new FileDimensions(300, 200))) + new ThumbnailSize(1024L * 1024L), new ThumbnailDimensions(300, 200))) .isInstanceOf(FileExtensionException.class); } } From 7624a6e8bda51f707700fc70e40c2b98e722fcd6 Mon Sep 17 00:00:00 2001 From: yumble Date: Wed, 6 Dec 2023 10:39:40 +0900 Subject: [PATCH 02/14] =?UTF-8?q?fix:=20default=20=EC=A0=91=EA=B7=BC?= =?UTF-8?q?=EC=A7=80=EC=A0=95=EC=9E=90=20->=20protected=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/courses/domain/Session.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/nextstep/courses/domain/Session.java b/src/main/java/nextstep/courses/domain/Session.java index 8c294fa07..b74be4d11 100644 --- a/src/main/java/nextstep/courses/domain/Session.java +++ b/src/main/java/nextstep/courses/domain/Session.java @@ -35,15 +35,15 @@ public boolean isEnrollmentPossible(Integer sessionFee) { } return true; } - boolean isRecruiting() { + protected boolean isRecruiting() { return sessionStatus == SessionStatus.RECRUITING; } - boolean isWithinCapacity() { + protected boolean isWithinCapacity() { return this.sessionType.isWithinCapacity(this.students.size()); } - boolean checkSessionFeeEquality(Integer sessionFee) { + protected boolean checkSessionFeeEquality(Integer sessionFee) { return this.sessionType.checkSessionFeeEquality(sessionFee); } From ede2296e2cafbe1e4be402119e86bf9b7acf9f31 Mon Sep 17 00:00:00 2001 From: yumble Date: Wed, 6 Dec 2023 10:41:22 +0900 Subject: [PATCH 03/14] =?UTF-8?q?remove:=20SessionType=20isPaid=20?= =?UTF-8?q?=ED=95=84=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nextstep/courses/domain/FreeSession.java | 4 ++-- src/main/java/nextstep/courses/domain/PaidSession.java | 3 +-- src/main/java/nextstep/courses/domain/SessionType.java | 9 +++------ 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/main/java/nextstep/courses/domain/FreeSession.java b/src/main/java/nextstep/courses/domain/FreeSession.java index c7499924d..9c98b4f4b 100644 --- a/src/main/java/nextstep/courses/domain/FreeSession.java +++ b/src/main/java/nextstep/courses/domain/FreeSession.java @@ -2,8 +2,8 @@ public class FreeSession extends SessionType{ - public FreeSession(boolean isPaid) { - super(isPaid); + public FreeSession() { + super(); } @Override diff --git a/src/main/java/nextstep/courses/domain/PaidSession.java b/src/main/java/nextstep/courses/domain/PaidSession.java index 7cf2599f7..2d0bc5787 100644 --- a/src/main/java/nextstep/courses/domain/PaidSession.java +++ b/src/main/java/nextstep/courses/domain/PaidSession.java @@ -5,8 +5,7 @@ public class PaidSession extends SessionType{ private final Integer maxStudents; private final Integer sessionFee; - public PaidSession(boolean isPaid, Integer maxStudents, Integer sessionFee) { - super(isPaid); + public PaidSession(Integer maxStudents, Integer sessionFee) { validatePaidValue(maxStudents, sessionFee); this.maxStudents = maxStudents; this.sessionFee = sessionFee; diff --git a/src/main/java/nextstep/courses/domain/SessionType.java b/src/main/java/nextstep/courses/domain/SessionType.java index bc8d4be3c..af1b6e95e 100644 --- a/src/main/java/nextstep/courses/domain/SessionType.java +++ b/src/main/java/nextstep/courses/domain/SessionType.java @@ -2,17 +2,14 @@ public abstract class SessionType { - private final boolean isPaid; - - public SessionType(boolean isPaid) { - this.isPaid = isPaid; + public SessionType() { } public static SessionType determineSessionType(boolean isPaid, Integer maxStudents, Integer sessionFee) { if (isPaid) { - return new PaidSession(isPaid, maxStudents, sessionFee); + return new PaidSession(maxStudents, sessionFee); } - return new FreeSession(isPaid); + return new FreeSession(); } public abstract boolean isWithinCapacity(Integer size); From dd535f1af7003c4f03c8d2bbe2f0d2eb2b704ea9 Mon Sep 17 00:00:00 2001 From: yumble Date: Wed, 6 Dec 2023 10:45:16 +0900 Subject: [PATCH 04/14] fix: SessionType abstract class -> interface --- .../java/nextstep/courses/domain/FreeSession.java | 3 +-- .../java/nextstep/courses/domain/PaidSession.java | 2 +- .../java/nextstep/courses/domain/SessionType.java | 11 ++++------- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/main/java/nextstep/courses/domain/FreeSession.java b/src/main/java/nextstep/courses/domain/FreeSession.java index 9c98b4f4b..ea2be81c1 100644 --- a/src/main/java/nextstep/courses/domain/FreeSession.java +++ b/src/main/java/nextstep/courses/domain/FreeSession.java @@ -1,9 +1,8 @@ package nextstep.courses.domain; -public class FreeSession extends SessionType{ +public class FreeSession implements SessionType{ public FreeSession() { - super(); } @Override diff --git a/src/main/java/nextstep/courses/domain/PaidSession.java b/src/main/java/nextstep/courses/domain/PaidSession.java index 2d0bc5787..ec7c8498f 100644 --- a/src/main/java/nextstep/courses/domain/PaidSession.java +++ b/src/main/java/nextstep/courses/domain/PaidSession.java @@ -1,6 +1,6 @@ package nextstep.courses.domain; -public class PaidSession extends SessionType{ +public class PaidSession implements SessionType{ private final Integer maxStudents; private final Integer sessionFee; diff --git a/src/main/java/nextstep/courses/domain/SessionType.java b/src/main/java/nextstep/courses/domain/SessionType.java index af1b6e95e..d14948e9f 100644 --- a/src/main/java/nextstep/courses/domain/SessionType.java +++ b/src/main/java/nextstep/courses/domain/SessionType.java @@ -1,17 +1,14 @@ package nextstep.courses.domain; -public abstract class SessionType { +public interface SessionType { - public SessionType() { - } - - public static SessionType determineSessionType(boolean isPaid, Integer maxStudents, Integer sessionFee) { + static SessionType determineSessionType(boolean isPaid, Integer maxStudents, Integer sessionFee) { if (isPaid) { return new PaidSession(maxStudents, sessionFee); } return new FreeSession(); } - public abstract boolean isWithinCapacity(Integer size); - public abstract boolean checkSessionFeeEquality(Integer sessionFee); + boolean isWithinCapacity(Integer size); + boolean checkSessionFeeEquality(Integer sessionFee); } From 9da12f1e653d7f336fa1f7ea3fad0accd87d9d37 Mon Sep 17 00:00:00 2001 From: yumble Date: Wed, 6 Dec 2023 11:32:42 +0900 Subject: [PATCH 05/14] =?UTF-8?q?docs=20:=20step3=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EB=B6=84=EC=84=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 382e9b668..4040b92d8 100644 --- a/README.md +++ b/README.md @@ -42,3 +42,17 @@ * [X] 강의 수강신청은 강의 상태가 모집중일 때만 가능하다. * [X] 유료 강의의 경우 결제는 이미 완료한 것으로 가정하고 이후 과정을 구현한다. * [X] 결제를 완료한 결제 정보는 payments 모듈을 통해 관리되며, 결제 정보는 Payment 객체에 담겨 반한된다. + +# STEP 3 기능분석 +* [ ] schema sql 작성 + * [ ] Session Schema sql 작성 + * [ ] Thumbnail Schema sql 작성 + * [ ] SessionStudents Schema sql 작성 +* [ ] data sql 작성 + * [ ] Session 예시 데이터 data.sql 작성 + * [ ] Thumbnail 예시 데이터 data.sql 작성 + * [ ] SessionStudents 예시 데이터 data.sql 작성 +* [ ] repository query 작성 + * [ ] Session Read,Update 쿼리 작성 + * [ ] SessionStudents Create, Read, Update 쿼리 작성 +* [ ] service enroll 코드 작성 \ No newline at end of file From a5ce8e411d1efc8b7e06e20813224422f8f8bc40 Mon Sep 17 00:00:00 2001 From: yumble Date: Wed, 6 Dec 2023 11:42:46 +0900 Subject: [PATCH 06/14] =?UTF-8?q?feat:=20Thumbnail=20Schema=20sql=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/resources/schema.sql | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4040b92d8..fd7ef719c 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ # STEP 3 기능분석 * [ ] schema sql 작성 * [ ] Session Schema sql 작성 - * [ ] Thumbnail Schema sql 작성 + * [X] Thumbnail Schema sql 작성 * [ ] SessionStudents Schema sql 작성 * [ ] data sql 작성 * [ ] Session 예시 데이터 data.sql 작성 diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 8d5a988c8..1309cbae8 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -48,3 +48,15 @@ create table delete_history ( deleted_by_id bigint, primary key (id) ); + +create table thumbnail ( + thumbnail_id bigint generated by default as identity, + name varchar(255) not null, + size bigint not null, + width int not null, + height int not null, + created_at timestamp not null, + updated_at timestamp, + writer_id bigint, + primary key (thumbnail_id) +); From e2476c7535a1598b1d4943890b2ae9ccad7233e9 Mon Sep 17 00:00:00 2001 From: yumble Date: Wed, 6 Dec 2023 13:06:16 +0900 Subject: [PATCH 07/14] =?UTF-8?q?feat:=20Session=20Schema=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=EB=B0=8F=20SessionType=20id=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- .../java/nextstep/courses/domain/FreeSession.java | 5 ++++- .../java/nextstep/courses/domain/PaidSession.java | 4 +++- .../java/nextstep/courses/domain/SessionType.java | 6 +++--- src/main/resources/schema.sql | 14 ++++++++++++++ .../java/nextstep/courses/domain/SessionTest.java | 10 +++++----- .../nextstep/courses/domain/SessionTypeTest.java | 8 ++++---- 7 files changed, 34 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index fd7ef719c..8a7ac049c 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ # STEP 3 기능분석 * [ ] schema sql 작성 - * [ ] Session Schema sql 작성 + * [X] Session Schema sql 작성 * [X] Thumbnail Schema sql 작성 * [ ] SessionStudents Schema sql 작성 * [ ] data sql 작성 diff --git a/src/main/java/nextstep/courses/domain/FreeSession.java b/src/main/java/nextstep/courses/domain/FreeSession.java index ea2be81c1..61f4a1a9a 100644 --- a/src/main/java/nextstep/courses/domain/FreeSession.java +++ b/src/main/java/nextstep/courses/domain/FreeSession.java @@ -2,7 +2,10 @@ public class FreeSession implements SessionType{ - public FreeSession() { + private final Long sessionTypeId; + + public FreeSession(Long sessionTypeId) { + this.sessionTypeId = sessionTypeId; } @Override diff --git a/src/main/java/nextstep/courses/domain/PaidSession.java b/src/main/java/nextstep/courses/domain/PaidSession.java index ec7c8498f..d25782051 100644 --- a/src/main/java/nextstep/courses/domain/PaidSession.java +++ b/src/main/java/nextstep/courses/domain/PaidSession.java @@ -2,11 +2,13 @@ public class PaidSession implements SessionType{ + private final Long sessionTypeId; private final Integer maxStudents; private final Integer sessionFee; - public PaidSession(Integer maxStudents, Integer sessionFee) { + public PaidSession(Long sessionTypeId, Integer maxStudents, Integer sessionFee) { validatePaidValue(maxStudents, sessionFee); + this.sessionTypeId = sessionTypeId; this.maxStudents = maxStudents; this.sessionFee = sessionFee; } diff --git a/src/main/java/nextstep/courses/domain/SessionType.java b/src/main/java/nextstep/courses/domain/SessionType.java index d14948e9f..6c73bdded 100644 --- a/src/main/java/nextstep/courses/domain/SessionType.java +++ b/src/main/java/nextstep/courses/domain/SessionType.java @@ -2,11 +2,11 @@ public interface SessionType { - static SessionType determineSessionType(boolean isPaid, Integer maxStudents, Integer sessionFee) { + static SessionType determineSessionType(boolean isPaid, Long sessionTypeId, Integer maxStudents, Integer sessionFee) { if (isPaid) { - return new PaidSession(maxStudents, sessionFee); + return new PaidSession(sessionTypeId, maxStudents, sessionFee); } - return new FreeSession(); + return new FreeSession(sessionTypeId); } boolean isWithinCapacity(Integer size); diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 1309cbae8..88339f1a6 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -60,3 +60,17 @@ create table thumbnail ( writer_id bigint, primary key (thumbnail_id) ); + +create table session ( + session_id bigint generated by default as identity, + name varchar(255) not null, + start_date date not null , + end_date date not null , + thumbnail_id bigint not null, + session_type_id bigint not null, + session_status varchar(20) not null + created_at timestamp not null, + updated_at timestamp, + writer_id bigint, + primary key (session_id) +); diff --git a/src/test/java/nextstep/courses/domain/SessionTest.java b/src/test/java/nextstep/courses/domain/SessionTest.java index 47eadc607..e93c0e633 100644 --- a/src/test/java/nextstep/courses/domain/SessionTest.java +++ b/src/test/java/nextstep/courses/domain/SessionTest.java @@ -14,7 +14,7 @@ public class SessionTest { private final Period period = new Period(LocalDate.of(2023, 12, 1), LocalDate.of(2023, 12, 25)); private final Thumbnail thumbnail = new Thumbnail(1, "thumbnail.png", 1024L * 1024L, 300, 200); private final List students = new ArrayList<>(List.of(NsUserTest.JAVAJIGI, NsUserTest.SANJIGI)); - private SessionType sessionType = SessionType.determineSessionType(true, 100, 100); + private SessionType sessionType = SessionType.determineSessionType(true, 1L, 100, 100); private SessionStatus sessionStatus = SessionStatus.RECRUITING; @Test @@ -47,7 +47,7 @@ public class SessionTest { @Test public void isWithinCapacity_유료강의_정원_마감_시_False_반환테스트() { - sessionType = SessionType.determineSessionType(true, 2, 10000); + sessionType = SessionType.determineSessionType(true, 1L, 2, 10000); Session fullSession = new Session(1L, "session", period, thumbnail, sessionType, sessionStatus, students); @@ -57,7 +57,7 @@ public class SessionTest { @Test public void isWithinCapacity_유료강의_정원_남을_시_True_반환테스트() { - sessionType = SessionType.determineSessionType(true, 3, 10000); + sessionType = SessionType.determineSessionType(true, 1L, 3, 10000); Session fullSession = new Session(1L, "session", period, thumbnail, sessionType, sessionStatus, students); @@ -67,7 +67,7 @@ public class SessionTest { @Test public void isWithinCapacity_무료강의_정원_마감되어도_True_반환테스트() { - sessionType = SessionType.determineSessionType(false, 2, 10000); + sessionType = SessionType.determineSessionType(false, 1L, 2, 10000); Session fullSession = new Session(1L, "session", period, thumbnail, sessionType, sessionStatus, students); @@ -91,7 +91,7 @@ public class SessionTest { @Test public void checkSessionFeeEquality_무료강의_수강료_일치여부_관계없이_True_반환테스트() { - sessionType = SessionType.determineSessionType(false, 2, 10000); + sessionType = SessionType.determineSessionType(false, 1L, 2, 10000); Session session = new Session(1L, "session", period, thumbnail, sessionType, sessionStatus, students); diff --git a/src/test/java/nextstep/courses/domain/SessionTypeTest.java b/src/test/java/nextstep/courses/domain/SessionTypeTest.java index cbdddfce1..aeb85f50c 100644 --- a/src/test/java/nextstep/courses/domain/SessionTypeTest.java +++ b/src/test/java/nextstep/courses/domain/SessionTypeTest.java @@ -9,25 +9,25 @@ public class SessionTypeTest { @Test public void 무료_강의_반환_테스트() { - SessionType sessionType = SessionType.determineSessionType(false, null, null); + SessionType sessionType = SessionType.determineSessionType(false, 1L, null, null); assertThat(sessionType).isExactlyInstanceOf(FreeSession.class); } @Test public void 유료_강의_반환_테스트() { - SessionType sessionType = SessionType.determineSessionType(true, 100, 10000); + SessionType sessionType = SessionType.determineSessionType(true, 1L, 100, 10000); assertThat(sessionType).isExactlyInstanceOf(PaidSession.class); } @Test public void 유료_강의_수강인원_에러_테스트() { - assertThatThrownBy(() -> SessionType.determineSessionType(true, -1, 10000)) + assertThatThrownBy(() -> SessionType.determineSessionType(true, 1L, -1, 10000)) .isInstanceOf(IllegalArgumentException.class); } @Test public void 유료_강의_수강료_에러_테스트() { - assertThatThrownBy(() -> SessionType.determineSessionType(true, 0, -1)) + assertThatThrownBy(() -> SessionType.determineSessionType(true, 1L, 0, -1)) .isInstanceOf(IllegalArgumentException.class); } } From 284bba093c7ed6ad87049fa41a2395e992947d31 Mon Sep 17 00:00:00 2001 From: yumble Date: Wed, 6 Dec 2023 13:09:50 +0900 Subject: [PATCH 08/14] =?UTF-8?q?feat:=20SessionType=20Schema=20sql=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FreeSession, PaidSession 분리해서 테이블 만듦 --- README.md | 7 +- src/main/resources/schema.sql | 127 +++++++++++++++++++++------------- 2 files changed, 81 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 8a7ac049c..96d5fdb3f 100644 --- a/README.md +++ b/README.md @@ -46,13 +46,14 @@ # STEP 3 기능분석 * [ ] schema sql 작성 * [X] Session Schema sql 작성 + * [X] SessionType Schema sql 작성 * [X] Thumbnail Schema sql 작성 - * [ ] SessionStudents Schema sql 작성 + * [ ] Students Schema sql 작성 * [ ] data sql 작성 * [ ] Session 예시 데이터 data.sql 작성 * [ ] Thumbnail 예시 데이터 data.sql 작성 - * [ ] SessionStudents 예시 데이터 data.sql 작성 + * [ ] Students 예시 데이터 data.sql 작성 * [ ] repository query 작성 * [ ] Session Read,Update 쿼리 작성 - * [ ] SessionStudents Create, Read, Update 쿼리 작성 + * [ ] Students Create, Read, Update 쿼리 작성 * [ ] service enroll 코드 작성 \ No newline at end of file diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index 88339f1a6..c409bf2ef 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -1,76 +1,103 @@ -create table course ( - id bigint generated by default as identity, - title varchar(255) not null, - creator_id bigint not null, - created_at timestamp not null, +create table course +( + id bigint generated by default as identity, + title varchar(255) not null, + creator_id bigint not null, + created_at timestamp not null, updated_at timestamp, primary key (id) ); -create table ns_user ( - id bigint generated by default as identity, - user_id varchar(20) not null, - password varchar(20) not null, - name varchar(20) not null, - email varchar(50), - created_at timestamp not null, +create table ns_user +( + id bigint generated by default as identity, + user_id varchar(20) not null, + password varchar(20) not null, + name varchar(20) not null, + email varchar(50), + created_at timestamp not null, updated_at timestamp, primary key (id) ); -create table question ( - id bigint generated by default as identity, - created_at timestamp not null, +create table question +( + id bigint generated by default as identity, + created_at timestamp not null, updated_at timestamp, - contents clob, - deleted boolean not null, - title varchar(100) not null, - writer_id bigint, + contents clob, + deleted boolean not null, + title varchar(100) not null, + writer_id bigint, primary key (id) ); -create table answer ( - id bigint generated by default as identity, - created_at timestamp not null, - updated_at timestamp, - contents clob, - deleted boolean not null, +create table answer +( + id bigint generated by default as identity, + created_at timestamp not null, + updated_at timestamp, + contents clob, + deleted boolean not null, question_id bigint, - writer_id bigint, + writer_id bigint, primary key (id) ); -create table delete_history ( - id bigint not null, - content_id bigint, - content_type varchar(255), - created_date timestamp, +create table delete_history +( + id bigint not null, + content_id bigint, + content_type varchar(255), + created_date timestamp, deleted_by_id bigint, primary key (id) ); -create table thumbnail ( +create table thumbnail +( thumbnail_id bigint generated by default as identity, - name varchar(255) not null, - size bigint not null, - width int not null, - height int not null, - created_at timestamp not null, - updated_at timestamp, - writer_id bigint, + name varchar(255) not null, + size bigint not null, + width int not null, + height int not null, + created_at timestamp not null, + updated_at timestamp, + writer_id bigint, primary key (thumbnail_id) ); -create table session ( - session_id bigint generated by default as identity, - name varchar(255) not null, - start_date date not null , - end_date date not null , - thumbnail_id bigint not null, - session_type_id bigint not null, - session_status varchar(20) not null - created_at timestamp not null, - updated_at timestamp, - writer_id bigint, +create table session +( + session_id bigint generated by default as identity, + name varchar(255) not null, + start_date date not null, + end_date date not null, + thumbnail_id bigint not null, + session_type_id bigint not null, + session_status varchar(20) not null + created_at timestamp not null, + updated_at timestamp, + writer_id bigint, primary key (session_id) ); + +create table session_type_free +( + session_type_id bigint generated by default as identity, + created_at timestamp not null, + updated_at timestamp, + writer_id bigint, + primary key (session_type_id) +); + +create table session_type_paid +( + session_type_id bigint generated by default as identity, + max_students int not null, + session_fee int not null, + created_at timestamp not null, + updated_at timestamp, + writer_id bigint, + primary key (session_type_id) +); From 2ccb9a4d2b7175430fc41f1016d2bb27a1e26cca Mon Sep 17 00:00:00 2001 From: yumble Date: Wed, 6 Dec 2023 13:13:43 +0900 Subject: [PATCH 09/14] =?UTF-8?q?feat:=20Students=20Schema=20sql=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- src/main/resources/schema.sql | 29 ++++++++++++++++++++--------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 96d5fdb3f..82e834b40 100644 --- a/README.md +++ b/README.md @@ -44,11 +44,11 @@ * [X] 결제를 완료한 결제 정보는 payments 모듈을 통해 관리되며, 결제 정보는 Payment 객체에 담겨 반한된다. # STEP 3 기능분석 -* [ ] schema sql 작성 +* [X] schema sql 작성 * [X] Session Schema sql 작성 * [X] SessionType Schema sql 작성 * [X] Thumbnail Schema sql 작성 - * [ ] Students Schema sql 작성 + * [X] Students Schema sql 작성 * [ ] data sql 작성 * [ ] Session 예시 데이터 data.sql 작성 * [ ] Thumbnail 예시 데이터 data.sql 작성 diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index c409bf2ef..d848acfa5 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -61,8 +61,8 @@ create table thumbnail size bigint not null, width int not null, height int not null, - created_at timestamp not null, - updated_at timestamp, + created_at timestamp not null default CURRENT_TIMESTAMP, + updated_at timestamp default CURRENT_TIMESTAMP, writer_id bigint, primary key (thumbnail_id) ); @@ -75,9 +75,9 @@ create table session end_date date not null, thumbnail_id bigint not null, session_type_id bigint not null, - session_status varchar(20) not null - created_at timestamp not null, - updated_at timestamp, + session_status varchar(20) not null, + created_at timestamp not null default CURRENT_TIMESTAMP, + updated_at timestamp default CURRENT_TIMESTAMP, writer_id bigint, primary key (session_id) ); @@ -85,8 +85,8 @@ create table session create table session_type_free ( session_type_id bigint generated by default as identity, - created_at timestamp not null, - updated_at timestamp, + created_at timestamp not null default CURRENT_TIMESTAMP, + updated_at timestamp default CURRENT_TIMESTAMP, writer_id bigint, primary key (session_type_id) ); @@ -96,8 +96,19 @@ create table session_type_paid session_type_id bigint generated by default as identity, max_students int not null, session_fee int not null, - created_at timestamp not null, - updated_at timestamp, + created_at timestamp not null default CURRENT_TIMESTAMP, + updated_at timestamp default CURRENT_TIMESTAMP, writer_id bigint, primary key (session_type_id) ); + +create table students +( + id bigint generated by default as identity, + session_id bigint not null, + student_id bigint not null, + created_at timestamp not null default CURRENT_TIMESTAMP, + updated_at timestamp default CURRENT_TIMESTAMP, + writer_id bigint, + primary key (id) +); From ba41c02725437472c4f04c93670c70ed4caf6821 Mon Sep 17 00:00:00 2001 From: yumble Date: Wed, 6 Dec 2023 13:22:02 +0900 Subject: [PATCH 10/14] =?UTF-8?q?feat:=20data=20sql=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 9 +++++---- src/main/resources/data.sql | 24 ++++++++++++++++++++++++ src/main/resources/schema.sql | 8 ++++---- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 82e834b40..be939b8b3 100644 --- a/README.md +++ b/README.md @@ -49,10 +49,11 @@ * [X] SessionType Schema sql 작성 * [X] Thumbnail Schema sql 작성 * [X] Students Schema sql 작성 -* [ ] data sql 작성 - * [ ] Session 예시 데이터 data.sql 작성 - * [ ] Thumbnail 예시 데이터 data.sql 작성 - * [ ] Students 예시 데이터 data.sql 작성 +* [X] data sql 작성 + * [X] Session 예시 데이터 data.sql 작성 + * [X] SessionType Schema sql 작성 + * [X] Thumbnail 예시 데이터 data.sql 작성 + * [X] Students 예시 데이터 data.sql 작성 * [ ] repository query 작성 * [ ] Session Read,Update 쿼리 작성 * [ ] Students Create, Read, Update 쿼리 작성 diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql index 4a6bc5a66..98a56d426 100644 --- a/src/main/resources/data.sql +++ b/src/main/resources/data.sql @@ -1,5 +1,6 @@ INSERT INTO ns_user (id, user_id, password, name, email, created_at) values (1, 'javajigi', 'test', '자바지기', 'javajigi@slipp.net', CURRENT_TIMESTAMP()); INSERT INTO ns_user (id, user_id, password, name, email, created_at) values (2, 'sanjigi', 'test', '산지기', 'sanjigi@slipp.net', CURRENT_TIMESTAMP()); +INSERT INTO ns_user (id, user_id, password, name, email, created_at) values (3, 'yumble', 'test', 'YUMBLE', 'yumble@naver.com', CURRENT_TIMESTAMP()); INSERT INTO question (id, writer_id, title, contents, created_at, deleted) VALUES (1, 1, '국내에서 Ruby on Rails와 Play가 활성화되기 힘든 이유는 뭘까?', 'Ruby on Rails(이하 RoR)는 2006년 즈음에 정말 뜨겁게 달아올랐다가 금방 가라 앉았다. Play 프레임워크는 정말 한 순간 잠시 눈에 뜨이다가 사라져 버렸다. RoR과 Play 기반으로 개발을 해보면 정말 생산성이 높으며, 웹 프로그래밍이 재미있기까지 하다. Spring MVC + JPA(Hibernate) 기반으로 진행하면 설정할 부분도 많고, 기본으로 지원하지 않는 기능도 많아 RoR과 Play에서 기본적으로 지원하는 기능을 서비스하려면 추가적인 개발이 필요하다.', CURRENT_TIMESTAMP(), false); @@ -8,3 +9,26 @@ INSERT INTO answer (writer_id, contents, created_at, question_id, deleted) VALUE INSERT INTO answer (writer_id, contents, created_at, question_id, deleted) VALUES (2, '언더스코어 강력 추천드려요. 다만 최신 버전을 공부하는 것보다는 0.10.0 버전부터 보는게 더 좋더군요. 코드의 변천사도 알 수 있고, 최적화되지 않은 코드들이 기능은 그대로 두고 최적화되어 가는 걸 보면 재미가 있습니다 :)', CURRENT_TIMESTAMP(), 1, false); INSERT INTO question (id, writer_id, title, contents, created_at, deleted) VALUES (2, 2, 'runtime 에 reflect 발동 주체 객체가 뭔지 알 방법이 있을까요?', '설계를 희한하게 하는 바람에 꼬인 문제같긴 합니다만. 여쭙습니다. 상황은 mybatis select 실행될 시에 return object 의 getter 가 호출되면서인데요. getter 안에 다른 property 에 의존중인 코드가 삽입되어 있어서, 만약 다른 mybatis select 구문에 해당 property 가 없다면 exception 이 발생하게 됩니다.', CURRENT_TIMESTAMP(), false); + +-- thumbnail 테이블 INSERT +INSERT INTO thumbnail (id, name, size, width, height, writer_id) +VALUES (1, 'thumbnail1.jpg', 1024 * 1024, 300, 200, 1), + (2, 'thumbnail2.jpg', 1024 * 1024, 600, 400, 2); + +-- session_type_free 테이블 INSERT +INSERT INTO session_type_free (session_type_id, writer_id) VALUES (1, 1); + +-- session_type_paid 테이블 INSERT +INSERT INTO session_type_paid (session_type_id, max_students, session_fee, writer_id) VALUES (2, 3, 10000, CURRENT_TIMESTAMP, 1); + +-- session 테이블 INSERT +INSERT INTO session (id, name, start_date, end_date, thumbnail_id, session_type_id, session_status, writer_id) +VALUES (1, 'Session FREE', '2023-11-01', '2023-12-31', 1, 1, 'RECRUITING', CURRENT_TIMESTAMP, 1), + (2, 'Session PAID, FULL 3 PEOPLE', '2023-11-01', '2023-12-31', 2, 2, 'RECRUITING', CURRENT_TIMESTAMP, 1); + +-- students 테이블 INSERT +INSERT INTO students (session_id, student_id, writer_id) +VALUES (1, 1, CURRENT_TIMESTAMP, 1), + (1, 2, CURRENT_TIMESTAMP, 2), + (2, 1, CURRENT_TIMESTAMP, 1), + (2, 2, CURRENT_TIMESTAMP, 2); diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index d848acfa5..c98d3017e 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -56,7 +56,7 @@ create table delete_history create table thumbnail ( - thumbnail_id bigint generated by default as identity, + id bigint generated by default as identity, name varchar(255) not null, size bigint not null, width int not null, @@ -64,12 +64,12 @@ create table thumbnail created_at timestamp not null default CURRENT_TIMESTAMP, updated_at timestamp default CURRENT_TIMESTAMP, writer_id bigint, - primary key (thumbnail_id) + primary key (id) ); create table session ( - session_id bigint generated by default as identity, + id bigint generated by default as identity, name varchar(255) not null, start_date date not null, end_date date not null, @@ -79,7 +79,7 @@ create table session created_at timestamp not null default CURRENT_TIMESTAMP, updated_at timestamp default CURRENT_TIMESTAMP, writer_id bigint, - primary key (session_id) + primary key (id) ); create table session_type_free From 383e2f3a512fce58ae2e80282edb95dfdc2c2a43 Mon Sep 17 00:00:00 2001 From: yumble Date: Fri, 8 Dec 2023 22:22:03 +0900 Subject: [PATCH 11/14] =?UTF-8?q?feat:=20Thumbnail=20Read=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + .../courses/domain/ThumbnailRepository.java | 5 ++++ .../JdbcThumbnailRepository.java | 29 +++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 src/main/java/nextstep/courses/domain/ThumbnailRepository.java create mode 100644 src/main/java/nextstep/courses/infrastructure/JdbcThumbnailRepository.java diff --git a/README.md b/README.md index be939b8b3..fe9803ad6 100644 --- a/README.md +++ b/README.md @@ -56,5 +56,6 @@ * [X] Students 예시 데이터 data.sql 작성 * [ ] repository query 작성 * [ ] Session Read,Update 쿼리 작성 + * [X] Thumbnail Read 쿼리 작성 * [ ] Students Create, Read, Update 쿼리 작성 * [ ] service enroll 코드 작성 \ No newline at end of file diff --git a/src/main/java/nextstep/courses/domain/ThumbnailRepository.java b/src/main/java/nextstep/courses/domain/ThumbnailRepository.java new file mode 100644 index 000000000..b84d2022a --- /dev/null +++ b/src/main/java/nextstep/courses/domain/ThumbnailRepository.java @@ -0,0 +1,5 @@ +package nextstep.courses.domain; + +public interface ThumbnailRepository { + Thumbnail findById(Integer id); +} diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcThumbnailRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcThumbnailRepository.java new file mode 100644 index 000000000..4e11aae8d --- /dev/null +++ b/src/main/java/nextstep/courses/infrastructure/JdbcThumbnailRepository.java @@ -0,0 +1,29 @@ +package nextstep.courses.infrastructure; + +import nextstep.courses.domain.Thumbnail; +import nextstep.courses.domain.ThumbnailRepository; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; + +@Repository("thumbnailRepository") +public class JdbcThumbnailRepository implements ThumbnailRepository { + private JdbcOperations jdbcTemplate; + + public JdbcThumbnailRepository(JdbcOperations jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public Thumbnail findById(Integer id) { + String sql = "select id, name, size, width, height from thumbnail where id = ?"; + RowMapper rowMapper = (rs, rowNum) -> new Thumbnail( + rs.getInt(1), + rs.getString(2), + rs.getLong(3), + rs.getInt(4), + rs.getInt(5)); + + return jdbcTemplate.queryForObject(sql, rowMapper, id); + } +} From 82879347af1a3c51edcc14038181f9ee621ed28c Mon Sep 17 00:00:00 2001 From: yumble Date: Fri, 8 Dec 2023 22:40:01 +0900 Subject: [PATCH 12/14] =?UTF-8?q?feat:=20Session=20Read=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- .../courses/domain/SessionRepository.java | 5 ++ .../nextstep/courses/domain/SessionType.java | 7 +++ .../infrastructure/JdbcSessionRepository.java | 63 +++++++++++++++++++ .../courses/service/SessionService.java | 11 +++- 5 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 src/main/java/nextstep/courses/domain/SessionRepository.java create mode 100644 src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java diff --git a/README.md b/README.md index fe9803ad6..5fa6ea1ce 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ * [X] Thumbnail 예시 데이터 data.sql 작성 * [X] Students 예시 데이터 data.sql 작성 * [ ] repository query 작성 - * [ ] Session Read,Update 쿼리 작성 + * [X] Session Read,Update 쿼리 작성 * [X] Thumbnail Read 쿼리 작성 - * [ ] Students Create, Read, Update 쿼리 작성 + * [ ] Students Read, Update 쿼리 작성 * [ ] service enroll 코드 작성 \ No newline at end of file diff --git a/src/main/java/nextstep/courses/domain/SessionRepository.java b/src/main/java/nextstep/courses/domain/SessionRepository.java new file mode 100644 index 000000000..8af1ae151 --- /dev/null +++ b/src/main/java/nextstep/courses/domain/SessionRepository.java @@ -0,0 +1,5 @@ +package nextstep.courses.domain; + +public interface SessionRepository { + Session findById(Long id); +} diff --git a/src/main/java/nextstep/courses/domain/SessionType.java b/src/main/java/nextstep/courses/domain/SessionType.java index 6c73bdded..5307b81fd 100644 --- a/src/main/java/nextstep/courses/domain/SessionType.java +++ b/src/main/java/nextstep/courses/domain/SessionType.java @@ -9,6 +9,13 @@ static SessionType determineSessionType(boolean isPaid, Long sessionTypeId, Inte return new FreeSession(sessionTypeId); } + static SessionType determineSessionTypeByDB(Long freeSessionTypeId, Long paidSessionTypeId, Integer maxStudents, Integer sessionFee) { + if (freeSessionTypeId == null) { + return new PaidSession(paidSessionTypeId, maxStudents, sessionFee); + } + return new FreeSession(freeSessionTypeId); + } + boolean isWithinCapacity(Integer size); boolean checkSessionFeeEquality(Integer sessionFee); } diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java new file mode 100644 index 000000000..0d3bb5e8e --- /dev/null +++ b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java @@ -0,0 +1,63 @@ +package nextstep.courses.infrastructure; + +import java.sql.Timestamp; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import nextstep.courses.domain.Course; +import nextstep.courses.domain.Period; +import nextstep.courses.domain.Session; +import nextstep.courses.domain.SessionRepository; +import nextstep.courses.domain.SessionStatus; +import nextstep.courses.domain.SessionType; +import nextstep.courses.domain.Thumbnail; +import nextstep.courses.domain.ThumbnailRepository; +import nextstep.users.domain.NsUser; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; + +@Repository("sessionRepository") +public class JdbcSessionRepository implements SessionRepository { + private JdbcOperations jdbcTemplate; + private final ThumbnailRepository thumbnailRepository; + + public JdbcSessionRepository(JdbcOperations jdbcTemplate, ThumbnailRepository thumbnailRepository) { + this.jdbcTemplate = jdbcTemplate; + this.thumbnailRepository = thumbnailRepository; + } + + @Override + public Session findById(Long id) { + String sql = "select id, name, start_date, end_date, thumbnail_id, session_status" + + " free.session_type_id, paid.session_type_id, max_students, session_fee" + + " from session " + + " left join session_type_free free on session.session_type_id = free.session_type_id" + + " left join session_type_paid paid on session.session_type_id = paid.session_type_id" + + "where id = ?"; + RowMapper rowMapper = (rs, rowNum) -> new Session( + rs.getLong(1), + rs.getString(2), + new Period(toLocalDate(rs.getTimestamp(3)), + toLocalDate(rs.getTimestamp(4))), + thumbnailRepository.findById(rs.getInt(5)), + SessionType.determineSessionTypeByDB( + rs.getLong(7), + rs.getLong(8), + rs.getInt(9), + rs.getInt(10) + ), + SessionStatus.valueOf(rs.getString(6)), + + null + ); + return jdbcTemplate.queryForObject(sql, rowMapper, id); + } + + private LocalDate toLocalDate(Timestamp timestamp) { + if (timestamp == null) { + return null; + } + return timestamp.toLocalDateTime().toLocalDate(); + } +} diff --git a/src/main/java/nextstep/courses/service/SessionService.java b/src/main/java/nextstep/courses/service/SessionService.java index df7ff4c6c..58d01d8c7 100644 --- a/src/main/java/nextstep/courses/service/SessionService.java +++ b/src/main/java/nextstep/courses/service/SessionService.java @@ -1,13 +1,20 @@ package nextstep.courses.service; import nextstep.courses.domain.Session; +import nextstep.courses.domain.SessionRepository; import nextstep.payments.domain.Payment; import nextstep.users.domain.NsUser; public class SessionService { - public void enroll(NsUser student, Integer sessionFee) { - Session session = null; //Todo Session DB코드 추가필요. + private final SessionRepository sessionRepository; + + public SessionService(SessionRepository sessionRepository) { + this.sessionRepository = sessionRepository; + } + + public void enroll(Long sessionId, NsUser student, Integer sessionFee) { + Session session = sessionRepository.findById(sessionId); if (session.isEnrollmentPossible(sessionFee)) { session.enroll(student); From b4320d3f7a5df6a403a356d74daddd15990cdf1f Mon Sep 17 00:00:00 2001 From: yumble Date: Sat, 9 Dec 2023 10:10:57 +0900 Subject: [PATCH 13/14] =?UTF-8?q?feat:=20Service=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 +-- .../java/nextstep/courses/domain/Session.java | 27 +++------ .../courses/domain/SessionStudents.java | 25 ++++++++ .../domain/SessionStudentsRepository.java | 7 +++ .../java/nextstep/courses/domain/Student.java | 22 +++++++ .../infrastructure/JdbcSessionRepository.java | 4 +- .../JdbcSessionStudentsRepository.java | 35 +++++++++++ .../courses/service/SessionService.java | 19 +++--- .../courses/domain/SessionStudentsTest.java | 43 ++++++++++++++ .../nextstep/courses/domain/SessionTest.java | 58 ++----------------- 10 files changed, 163 insertions(+), 85 deletions(-) create mode 100644 src/main/java/nextstep/courses/domain/SessionStudents.java create mode 100644 src/main/java/nextstep/courses/domain/SessionStudentsRepository.java create mode 100644 src/main/java/nextstep/courses/domain/Student.java create mode 100644 src/main/java/nextstep/courses/infrastructure/JdbcSessionStudentsRepository.java create mode 100644 src/test/java/nextstep/courses/domain/SessionStudentsTest.java diff --git a/README.md b/README.md index 5fa6ea1ce..730274fad 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,8 @@ * [X] SessionType Schema sql 작성 * [X] Thumbnail 예시 데이터 data.sql 작성 * [X] Students 예시 데이터 data.sql 작성 -* [ ] repository query 작성 - * [X] Session Read,Update 쿼리 작성 +* [X] repository query 작성 + * [X] Session Read 쿼리 작성 * [X] Thumbnail Read 쿼리 작성 - * [ ] Students Read, Update 쿼리 작성 -* [ ] service enroll 코드 작성 \ No newline at end of file + * [X] Students Read, Save 쿼리 작성 +* [X] service enroll 코드 작성 \ No newline at end of file diff --git a/src/main/java/nextstep/courses/domain/Session.java b/src/main/java/nextstep/courses/domain/Session.java index b74be4d11..4dcc3fcdb 100644 --- a/src/main/java/nextstep/courses/domain/Session.java +++ b/src/main/java/nextstep/courses/domain/Session.java @@ -10,24 +10,22 @@ public class Session { private final Thumbnail thumbnail; private final SessionType sessionType; private final SessionStatus sessionStatus; - private final List students; public Session(Long sessionId, String sessionName, Period sessionPeriod, Thumbnail thumbnail, - SessionType sessionType, SessionStatus sessionStatus, List students) { + SessionType sessionType, SessionStatus sessionStatus) { this.sessionId = sessionId; this.sessionName = sessionName; this.sessionPeriod = sessionPeriod; this.thumbnail = thumbnail; this.sessionType = sessionType; this.sessionStatus = sessionStatus; - this.students = students; } - public boolean isEnrollmentPossible(Integer sessionFee) { + public boolean isEnrollmentPossible(SessionStudents students, Integer sessionFee) { if (!isRecruiting()) { return false; } - if (!isWithinCapacity()) { + if (!isWithinCapacity(students)) { return false; } if (!checkSessionFeeEquality(sessionFee)) { @@ -39,24 +37,18 @@ protected boolean isRecruiting() { return sessionStatus == SessionStatus.RECRUITING; } - protected boolean isWithinCapacity() { - return this.sessionType.isWithinCapacity(this.students.size()); + protected boolean isWithinCapacity(SessionStudents students) { + return students.isWithinCapacity(this.sessionType); } protected boolean checkSessionFeeEquality(Integer sessionFee) { return this.sessionType.checkSessionFeeEquality(sessionFee); } - public void enroll(NsUser student) { - this.students.add(student); - } - - public Long getSessionId() { - return sessionId; - } - - public List getStudents() { - return students; + public Student enroll(SessionStudents students, NsUser user) { + Student student = new Student(this.sessionId, user.getId()); + students.enroll(student); + return student; } @Override @@ -68,7 +60,6 @@ public String toString() { ", thumbnail=" + thumbnail + ", sessionType=" + sessionType + ", sessionStatus=" + sessionStatus + - ", students=" + students + '}'; } } diff --git a/src/main/java/nextstep/courses/domain/SessionStudents.java b/src/main/java/nextstep/courses/domain/SessionStudents.java new file mode 100644 index 000000000..f11ae623a --- /dev/null +++ b/src/main/java/nextstep/courses/domain/SessionStudents.java @@ -0,0 +1,25 @@ +package nextstep.courses.domain; + +import java.util.List; +import nextstep.users.domain.NsUser; + +public class SessionStudents { + + private final List students; + + public SessionStudents(List students) { + this.students = students; + } + + public void enroll(Student student) { + students.add(student); + } + + public boolean isWithinCapacity(SessionType sessionType) { + return sessionType.isWithinCapacity(students.size()); + } + + public List getStudents() { + return students; + } +} diff --git a/src/main/java/nextstep/courses/domain/SessionStudentsRepository.java b/src/main/java/nextstep/courses/domain/SessionStudentsRepository.java new file mode 100644 index 000000000..0204335a3 --- /dev/null +++ b/src/main/java/nextstep/courses/domain/SessionStudentsRepository.java @@ -0,0 +1,7 @@ +package nextstep.courses.domain; + +public interface SessionStudentsRepository { + int save(Student student); + + SessionStudents findBySessionId(Long sessionId); +} diff --git a/src/main/java/nextstep/courses/domain/Student.java b/src/main/java/nextstep/courses/domain/Student.java new file mode 100644 index 000000000..271558139 --- /dev/null +++ b/src/main/java/nextstep/courses/domain/Student.java @@ -0,0 +1,22 @@ +package nextstep.courses.domain; + +public class Student { + + private Long id; + private final Long sessionId; + private final Long studentId; + + public Student(Long sessionId, Long studentId) { + this(null, sessionId, studentId); + } + + public Student(Long id, Long sessionId, Long studentId) { + this.id = id; + this.sessionId = sessionId; + this.studentId = studentId; + } + + public Long getSessionId() { + return sessionId; + } +} diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java index 0d3bb5e8e..a1d5b55e0 100644 --- a/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java +++ b/src/main/java/nextstep/courses/infrastructure/JdbcSessionRepository.java @@ -47,9 +47,7 @@ public Session findById(Long id) { rs.getInt(9), rs.getInt(10) ), - SessionStatus.valueOf(rs.getString(6)), - - null + SessionStatus.valueOf(rs.getString(6)) ); return jdbcTemplate.queryForObject(sql, rowMapper, id); } diff --git a/src/main/java/nextstep/courses/infrastructure/JdbcSessionStudentsRepository.java b/src/main/java/nextstep/courses/infrastructure/JdbcSessionStudentsRepository.java new file mode 100644 index 000000000..89d1bfc9a --- /dev/null +++ b/src/main/java/nextstep/courses/infrastructure/JdbcSessionStudentsRepository.java @@ -0,0 +1,35 @@ +package nextstep.courses.infrastructure; + +import nextstep.courses.domain.SessionStudents; +import nextstep.courses.domain.SessionStudentsRepository; +import nextstep.courses.domain.Student; +import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; + +@Repository("sessionStudentsRepository") +public class JdbcSessionStudentsRepository implements SessionStudentsRepository { + private JdbcOperations jdbcTemplate; + + public JdbcSessionStudentsRepository(JdbcOperations jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public int save(Student student) { + String sql = "insert into students (session_id, student_Id) values(?, ?)"; + + return jdbcTemplate.update(sql, student.getSessionId(), student.getSessionId()); + } + + @Override + public SessionStudents findBySessionId(Long sessionId) { + String sql = "select id, session_id, student_id from students where session_id = ?"; + RowMapper rowMapper = (rs, rowNum) -> new Student( + rs.getLong(1), + rs.getLong(2), + rs.getLong(3)); + + return new SessionStudents(jdbcTemplate.query(sql, rowMapper, sessionId)); + } +} diff --git a/src/main/java/nextstep/courses/service/SessionService.java b/src/main/java/nextstep/courses/service/SessionService.java index 58d01d8c7..36a245704 100644 --- a/src/main/java/nextstep/courses/service/SessionService.java +++ b/src/main/java/nextstep/courses/service/SessionService.java @@ -2,25 +2,28 @@ import nextstep.courses.domain.Session; import nextstep.courses.domain.SessionRepository; -import nextstep.payments.domain.Payment; +import nextstep.courses.domain.SessionStudents; +import nextstep.courses.domain.SessionStudentsRepository; +import nextstep.courses.domain.Student; import nextstep.users.domain.NsUser; public class SessionService { private final SessionRepository sessionRepository; + private final SessionStudentsRepository studentsRepository; - public SessionService(SessionRepository sessionRepository) { + public SessionService(SessionRepository sessionRepository, SessionStudentsRepository studentsRepository) { this.sessionRepository = sessionRepository; + this.studentsRepository = studentsRepository; } - public void enroll(Long sessionId, NsUser student, Integer sessionFee) { + public void enroll(Long sessionId, NsUser user, Integer sessionFee) { Session session = sessionRepository.findById(sessionId); + SessionStudents students = studentsRepository.findBySessionId(sessionId); - if (session.isEnrollmentPossible(sessionFee)) { - session.enroll(student); - //todo Payment 설정 필요 - Payment payment = new Payment("paymentId", session.getSessionId(), student.getId(), sessionFee); - //todo student, payment DB저장 필요 + if (session.isEnrollmentPossible(students, sessionFee)) { + Student student = session.enroll(students, user); + studentsRepository.save(student); } } diff --git a/src/test/java/nextstep/courses/domain/SessionStudentsTest.java b/src/test/java/nextstep/courses/domain/SessionStudentsTest.java new file mode 100644 index 000000000..4aaf82ba6 --- /dev/null +++ b/src/test/java/nextstep/courses/domain/SessionStudentsTest.java @@ -0,0 +1,43 @@ +package nextstep.courses.domain; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.List; +import nextstep.users.domain.NsUserTest; +import org.junit.jupiter.api.Test; + +public class SessionStudentsTest { + + private Student javajigi = new Student(1L, NsUserTest.JAVAJIGI.getId()); + private Student sanjigi = new Student(1L, NsUserTest.SANJIGI.getId()); + private SessionStudents students = new SessionStudents(new ArrayList<>(List.of(javajigi))); + + @Test + public void isWithinCapacity_유료강의_정원_마감_시_False_반환테스트() { + SessionType paidSessionType = SessionType.determineSessionType(true, 1L, 1, 100); + + assertThat(students.isWithinCapacity(paidSessionType)).isFalse(); + } + + @Test + public void isWithinCapacity_유료강의_정원_남을_시_True_반환테스트() { + SessionType paidSessionType = SessionType.determineSessionType(true, 1L, 2, 100); + + assertThat(students.isWithinCapacity(paidSessionType)).isTrue(); + } + + @Test + public void isWithinCapacity_무료강의_정원_마감되어도_True_반환테스트() { + SessionType freeSessionType = SessionType.determineSessionType(false, 1L, null, null); + + assertThat(students.isWithinCapacity(freeSessionType)).isTrue(); + } + + @Test + public void enroll_Students_사이즈_증가_테스트() { + students.enroll(sanjigi); + + assertThat(students.getStudents().size()).isEqualTo(2); + } +} diff --git a/src/test/java/nextstep/courses/domain/SessionTest.java b/src/test/java/nextstep/courses/domain/SessionTest.java index e93c0e633..9b0801932 100644 --- a/src/test/java/nextstep/courses/domain/SessionTest.java +++ b/src/test/java/nextstep/courses/domain/SessionTest.java @@ -3,24 +3,19 @@ import static org.assertj.core.api.Assertions.assertThat; import java.time.LocalDate; -import java.util.ArrayList; -import java.util.List; -import nextstep.users.domain.NsUser; -import nextstep.users.domain.NsUserTest; import org.junit.jupiter.api.Test; public class SessionTest { private final Period period = new Period(LocalDate.of(2023, 12, 1), LocalDate.of(2023, 12, 25)); private final Thumbnail thumbnail = new Thumbnail(1, "thumbnail.png", 1024L * 1024L, 300, 200); - private final List students = new ArrayList<>(List.of(NsUserTest.JAVAJIGI, NsUserTest.SANJIGI)); private SessionType sessionType = SessionType.determineSessionType(true, 1L, 100, 100); private SessionStatus sessionStatus = SessionStatus.RECRUITING; @Test public void isRecruiting_모집중일때_TRUE_반환테스트() { Session recruitingSession = new Session(1L, "session", period, thumbnail, - sessionType, sessionStatus, students); + sessionType, sessionStatus); assertThat(recruitingSession.isRecruiting()).isTrue(); } @@ -30,7 +25,7 @@ public class SessionTest { sessionStatus = SessionStatus.FINISHED; Session finishedSession = new Session(1L, "session", period, thumbnail, - sessionType, sessionStatus, students); + sessionType, sessionStatus); assertThat(finishedSession.isRecruiting()).isFalse(); } @@ -40,52 +35,22 @@ public class SessionTest { sessionStatus = SessionStatus.PREPARING; Session preparingSession = new Session(1L, "session", period, thumbnail, - sessionType, sessionStatus, students); + sessionType, sessionStatus); assertThat(preparingSession.isRecruiting()).isFalse(); } - @Test - public void isWithinCapacity_유료강의_정원_마감_시_False_반환테스트() { - sessionType = SessionType.determineSessionType(true, 1L, 2, 10000); - - Session fullSession = new Session(1L, "session", period, thumbnail, - sessionType, sessionStatus, students); - - assertThat(fullSession.isWithinCapacity()).isFalse(); - } - - @Test - public void isWithinCapacity_유료강의_정원_남을_시_True_반환테스트() { - sessionType = SessionType.determineSessionType(true, 1L, 3, 10000); - - Session fullSession = new Session(1L, "session", period, thumbnail, - sessionType, sessionStatus, students); - - assertThat(fullSession.isWithinCapacity()).isTrue(); - } - - @Test - public void isWithinCapacity_무료강의_정원_마감되어도_True_반환테스트() { - sessionType = SessionType.determineSessionType(false, 1L, 2, 10000); - - Session fullSession = new Session(1L, "session", period, thumbnail, - sessionType, sessionStatus, students); - - assertThat(fullSession.isWithinCapacity()).isTrue(); - } - @Test public void checkSessionFeeEquality_수강료_일치_시_True_반환테스트() { Session session = new Session(1L, "session", period, thumbnail, - sessionType, sessionStatus, students); + sessionType, sessionStatus); assertThat(session.checkSessionFeeEquality(100)).isTrue(); } @Test public void checkSessionFeeEquality_수강료_불일치_시_False_반환테스트() { Session session = new Session(1L, "session", period, thumbnail, - sessionType, sessionStatus, students); + sessionType, sessionStatus); assertThat(session.checkSessionFeeEquality(3000)).isFalse(); } @@ -94,18 +59,7 @@ public class SessionTest { sessionType = SessionType.determineSessionType(false, 1L, 2, 10000); Session session = new Session(1L, "session", period, thumbnail, - sessionType, sessionStatus, students); + sessionType, sessionStatus); assertThat(session.checkSessionFeeEquality(3000)).isTrue(); } - - @Test - public void enroll_수강생_추가_리스트_테스트() { - NsUser yumble = new NsUser(); - Session session = new Session(1L, "session", period, thumbnail, - sessionType, sessionStatus, students); - - session.enroll(yumble); - - assertThat(session.getStudents()).isEqualTo(List.of(NsUserTest.JAVAJIGI, NsUserTest.SANJIGI, yumble)); - } } From b05446e8dbd1bf4f3f1ea32ee6f98020a78f90e9 Mon Sep 17 00:00:00 2001 From: yumble Date: Sat, 9 Dec 2023 11:06:50 +0900 Subject: [PATCH 14/14] =?UTF-8?q?test:=20SessionService=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/nextstep/courses/domain/Session.java | 14 +- .../courses/domain/SessionStudents.java | 1 - .../java/nextstep/courses/domain/Student.java | 20 +++ .../courses/exception/SessionException.java | 27 ++++ .../courses/service/SessionService.java | 8 +- .../courses/service/SessionServiceTest.java | 126 ++++++++++++++++++ 6 files changed, 191 insertions(+), 5 deletions(-) create mode 100644 src/main/java/nextstep/courses/exception/SessionException.java create mode 100644 src/test/java/nextstep/courses/service/SessionServiceTest.java diff --git a/src/main/java/nextstep/courses/domain/Session.java b/src/main/java/nextstep/courses/domain/Session.java index 4dcc3fcdb..832080c7c 100644 --- a/src/main/java/nextstep/courses/domain/Session.java +++ b/src/main/java/nextstep/courses/domain/Session.java @@ -1,6 +1,10 @@ package nextstep.courses.domain; import java.util.List; +import nextstep.courses.exception.SessionException; +import nextstep.courses.exception.SessionException.SessionFeeNotEqualException; +import nextstep.courses.exception.SessionException.SessionFullException; +import nextstep.courses.exception.SessionException.SessionNotOpenException; import nextstep.users.domain.NsUser; public class Session { @@ -23,13 +27,13 @@ public Session(Long sessionId, String sessionName, Period sessionPeriod, Thumbna public boolean isEnrollmentPossible(SessionStudents students, Integer sessionFee) { if (!isRecruiting()) { - return false; + throw new SessionNotOpenException("강의가 모집중인 상태가 아닙니다."); } if (!isWithinCapacity(students)) { - return false; + throw new SessionFullException("강의의 수용인원이 다 찼습니다."); } if (!checkSessionFeeEquality(sessionFee)) { - return false; + throw new SessionFeeNotEqualException("접수하신 수강료가 강의 수강료와 일치하지 않습니다."); } return true; } @@ -51,6 +55,10 @@ public Student enroll(SessionStudents students, NsUser user) { return student; } + public Long getSessionId() { + return sessionId; + } + @Override public String toString() { return "Session{" + diff --git a/src/main/java/nextstep/courses/domain/SessionStudents.java b/src/main/java/nextstep/courses/domain/SessionStudents.java index f11ae623a..d2fdd894d 100644 --- a/src/main/java/nextstep/courses/domain/SessionStudents.java +++ b/src/main/java/nextstep/courses/domain/SessionStudents.java @@ -1,7 +1,6 @@ package nextstep.courses.domain; import java.util.List; -import nextstep.users.domain.NsUser; public class SessionStudents { diff --git a/src/main/java/nextstep/courses/domain/Student.java b/src/main/java/nextstep/courses/domain/Student.java index 271558139..c9351292e 100644 --- a/src/main/java/nextstep/courses/domain/Student.java +++ b/src/main/java/nextstep/courses/domain/Student.java @@ -1,5 +1,7 @@ package nextstep.courses.domain; +import java.util.Objects; + public class Student { private Long id; @@ -19,4 +21,22 @@ public Student(Long id, Long sessionId, Long studentId) { public Long getSessionId() { return sessionId; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Student student = (Student) o; + return Objects.equals(sessionId, student.sessionId) + && Objects.equals(studentId, student.studentId); + } + + @Override + public int hashCode() { + return Objects.hash(sessionId, studentId); + } } diff --git a/src/main/java/nextstep/courses/exception/SessionException.java b/src/main/java/nextstep/courses/exception/SessionException.java new file mode 100644 index 000000000..e4eb4e041 --- /dev/null +++ b/src/main/java/nextstep/courses/exception/SessionException.java @@ -0,0 +1,27 @@ +package nextstep.courses.exception; + +public class SessionException extends IllegalArgumentException{ + public SessionException() { + } + + public SessionException(String message) { + super(message); + } + public static class SessionNotOpenException extends SessionException { + public SessionNotOpenException(String message) { + super(message); + } + } + public static class SessionFullException extends SessionException { + public SessionFullException(String message) { + super(message); + } + } + + public static class SessionFeeNotEqualException extends SessionException { + public SessionFeeNotEqualException(String message) { + super(message); + } + } +} + diff --git a/src/main/java/nextstep/courses/service/SessionService.java b/src/main/java/nextstep/courses/service/SessionService.java index 36a245704..f13110ed5 100644 --- a/src/main/java/nextstep/courses/service/SessionService.java +++ b/src/main/java/nextstep/courses/service/SessionService.java @@ -1,15 +1,21 @@ package nextstep.courses.service; +import javax.annotation.Resource; import nextstep.courses.domain.Session; import nextstep.courses.domain.SessionRepository; import nextstep.courses.domain.SessionStudents; import nextstep.courses.domain.SessionStudentsRepository; import nextstep.courses.domain.Student; import nextstep.users.domain.NsUser; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +@Service("sessionService") public class SessionService { + @Resource(name = "sessionRepository") private final SessionRepository sessionRepository; + @Resource(name = "sessionStudentsRepository") private final SessionStudentsRepository studentsRepository; public SessionService(SessionRepository sessionRepository, SessionStudentsRepository studentsRepository) { @@ -17,6 +23,7 @@ public SessionService(SessionRepository sessionRepository, SessionStudentsReposi this.studentsRepository = studentsRepository; } + @Transactional public void enroll(Long sessionId, NsUser user, Integer sessionFee) { Session session = sessionRepository.findById(sessionId); SessionStudents students = studentsRepository.findBySessionId(sessionId); @@ -25,6 +32,5 @@ public void enroll(Long sessionId, NsUser user, Integer sessionFee) { Student student = session.enroll(students, user); studentsRepository.save(student); } - } } diff --git a/src/test/java/nextstep/courses/service/SessionServiceTest.java b/src/test/java/nextstep/courses/service/SessionServiceTest.java new file mode 100644 index 000000000..443a4d531 --- /dev/null +++ b/src/test/java/nextstep/courses/service/SessionServiceTest.java @@ -0,0 +1,126 @@ +package nextstep.courses.service; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; +import nextstep.courses.domain.Period; +import nextstep.courses.domain.Session; +import nextstep.courses.domain.SessionRepository; +import nextstep.courses.domain.SessionStatus; +import nextstep.courses.domain.SessionStudents; +import nextstep.courses.domain.SessionStudentsRepository; +import nextstep.courses.domain.SessionType; +import nextstep.courses.domain.Student; +import nextstep.courses.domain.Thumbnail; +import nextstep.courses.exception.SessionException.SessionFeeNotEqualException; +import nextstep.courses.exception.SessionException.SessionFullException; +import nextstep.courses.exception.SessionException.SessionNotOpenException; +import nextstep.qna.CannotDeleteException; +import nextstep.qna.domain.Answer; +import nextstep.qna.domain.ContentType; +import nextstep.qna.domain.DeleteHistory; +import nextstep.qna.domain.Question; +import nextstep.qna.domain.QuestionRepository; +import nextstep.qna.service.DeleteHistoryService; +import nextstep.qna.service.QnAService; +import nextstep.users.domain.NsUserTest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class SessionServiceTest { + @Mock + private SessionRepository sessionRepository; + + @Mock + private SessionStudentsRepository studentsRepository; + + @InjectMocks + private SessionService sessionService; + + private final Period period = new Period(LocalDate.of(2023, 12, 1), LocalDate.of(2023, 12, 25)); + private final Thumbnail thumbnail = new Thumbnail(1, "thumbnail.png", 1024L * 1024L, 300, 200); + private final Student javajigi = new Student(1L, NsUserTest.JAVAJIGI.getId()); + private final Student sanjigi = new Student(1L, NsUserTest.SANJIGI.getId()); + + private SessionType sessionType = SessionType.determineSessionType(true, 1L, 2, 100); + private SessionStatus sessionStatus = SessionStatus.RECRUITING; + + private Session session; + private SessionStudents students; + + + @BeforeEach + public void setUp() { + session = new Session(1L, "session", period, thumbnail, + sessionType, sessionStatus); + students = new SessionStudents(new ArrayList<>(List.of(javajigi))); + } + + @Test + public void enroll_정원_남았을_시_성공() { + when(sessionRepository.findById(session.getSessionId())).thenReturn(session); + when(studentsRepository.findBySessionId(session.getSessionId())).thenReturn(students); + + assertThat(session.getSessionId()).isEqualTo(1L); + sessionService.enroll(session.getSessionId(), NsUserTest.SANJIGI, 100); + + assertThat(students.getStudents().size()).isEqualTo(2); + + verify(studentsRepository).save(sanjigi); + } + + @Test + public void enroll_정원_찼을_시_실패() { + sessionType = SessionType.determineSessionType(true, 1L, 1, 100); + + session = new Session(1L, "session", period, thumbnail, + sessionType, sessionStatus); + + when(sessionRepository.findById(session.getSessionId())).thenReturn(session); + when(studentsRepository.findBySessionId(session.getSessionId())).thenReturn(students); + + assertThat(session.getSessionId()).isEqualTo(1L); + assertThatThrownBy(() -> sessionService.enroll(session.getSessionId(), NsUserTest.SANJIGI, 100)) + .isInstanceOf(SessionFullException.class); + } + + @Test + public void enroll_모집_중_아닐_시_실패() { + sessionStatus = SessionStatus.PREPARING; + + session = new Session(1L, "session", period, thumbnail, + sessionType, sessionStatus); + + when(sessionRepository.findById(session.getSessionId())).thenReturn(session); + when(studentsRepository.findBySessionId(session.getSessionId())).thenReturn(students); + + assertThat(session.getSessionId()).isEqualTo(1L); + assertThatThrownBy(() -> sessionService.enroll(session.getSessionId(), NsUserTest.SANJIGI, 100)) + .isInstanceOf(SessionNotOpenException.class); + } + + + @Test + public void enroll_강의료_불일치_시_실패() { + when(sessionRepository.findById(session.getSessionId())).thenReturn(session); + when(studentsRepository.findBySessionId(session.getSessionId())).thenReturn(students); + + assertThat(session.getSessionId()).isEqualTo(1L); + assertThatThrownBy(() -> sessionService.enroll(session.getSessionId(), NsUserTest.SANJIGI, 300)) + .isInstanceOf(SessionFeeNotEqualException.class); + } + +}