From c3db2198fe8a28caa20a4e6db3ccfa527fa11e16 Mon Sep 17 00:00:00 2001 From: dwl21 Date: Sun, 2 Feb 2025 11:14:51 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EA=B5=90=EC=96=91=20=ED=95=84=EC=88=98?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../course/application/CourseController.kt | 7 ++++ .../dto/GeneralRequiredCourseRequest.kt | 16 ++++++++++ .../domain/course/business/CourseService.kt | 10 ++++++ .../domain/course/implement/CourseReader.kt | 4 +++ src/main/resources/http/course.http | 6 ++++ .../common/support/fixture/CourseFixture.kt | 10 +++++- .../storage/business/CourseServiceTest.kt | 32 +++++++++++++++++++ 7 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/com/yourssu/soongpt/domain/course/application/dto/GeneralRequiredCourseRequest.kt diff --git a/src/main/kotlin/com/yourssu/soongpt/domain/course/application/CourseController.kt b/src/main/kotlin/com/yourssu/soongpt/domain/course/application/CourseController.kt index 584c265..9a7be36 100644 --- a/src/main/kotlin/com/yourssu/soongpt/domain/course/application/CourseController.kt +++ b/src/main/kotlin/com/yourssu/soongpt/domain/course/application/CourseController.kt @@ -1,6 +1,7 @@ package com.yourssu.soongpt.domain.course.application import com.yourssu.soongpt.common.business.dto.Response +import com.yourssu.soongpt.domain.course.application.dto.GeneralRequiredCourseRequest import com.yourssu.soongpt.domain.course.application.dto.MajorElectiveCourseRequest import com.yourssu.soongpt.domain.course.application.dto.MajorRequiredCourseRequest import com.yourssu.soongpt.domain.course.business.CourseService @@ -28,4 +29,10 @@ class CourseController( val response = courseService.findByDepartmentNameInMajorElective(request.department) return ResponseEntity.ok().body(Response(result = response)) } + + @GetMapping("/general/required") + fun getGeneralRequiredCourses(@Valid @ModelAttribute request: GeneralRequiredCourseRequest): ResponseEntity>> { + val response = courseService.findByDepartmentNameInGeneralRequired(request.department) + return ResponseEntity.ok().body(Response(result = response)) + } } \ No newline at end of file diff --git a/src/main/kotlin/com/yourssu/soongpt/domain/course/application/dto/GeneralRequiredCourseRequest.kt b/src/main/kotlin/com/yourssu/soongpt/domain/course/application/dto/GeneralRequiredCourseRequest.kt new file mode 100644 index 0000000..ca2ff17 --- /dev/null +++ b/src/main/kotlin/com/yourssu/soongpt/domain/course/application/dto/GeneralRequiredCourseRequest.kt @@ -0,0 +1,16 @@ +package com.yourssu.soongpt.domain.course.application.dto + +import jakarta.validation.constraints.NotBlank +import org.hibernate.validator.constraints.Range + +data class GeneralRequiredCourseRequest( + @Range(min = 15, max = 25, message = "학번은 15부터 25까지 가능합니다.") + val schoolId: Long, + + @NotBlank + val department: String, + + @Range(min = 1, max = 5, message = "학년은 1부터 5까지 가능합니다.") + val grade: Int, +) { +} \ No newline at end of file diff --git a/src/main/kotlin/com/yourssu/soongpt/domain/course/business/CourseService.kt b/src/main/kotlin/com/yourssu/soongpt/domain/course/business/CourseService.kt index 717ea34..5fdd14b 100644 --- a/src/main/kotlin/com/yourssu/soongpt/domain/course/business/CourseService.kt +++ b/src/main/kotlin/com/yourssu/soongpt/domain/course/business/CourseService.kt @@ -33,4 +33,14 @@ class CourseService( CourseResponse.from(course = it, target = targets, courseTimes = courseTimes) } } + + fun findByDepartmentNameInGeneralRequired(departmentName: String): List { + val department = departmentReader.getByName(departmentName) + val courses = courseReader.findAllByDepartmentIdInGeneralRequired(department.id!!) + return courses.map { + val targets = targetReader.findAllBy(courseId = it.id!!, department = department) + val courseTimes = courseTimeReader.findAllByCourseId(it.id) + CourseResponse.from(course = it, target = targets, courseTimes = courseTimes) + } + } } \ No newline at end of file diff --git a/src/main/kotlin/com/yourssu/soongpt/domain/course/implement/CourseReader.kt b/src/main/kotlin/com/yourssu/soongpt/domain/course/implement/CourseReader.kt index ef1f728..8c02c2a 100644 --- a/src/main/kotlin/com/yourssu/soongpt/domain/course/implement/CourseReader.kt +++ b/src/main/kotlin/com/yourssu/soongpt/domain/course/implement/CourseReader.kt @@ -13,4 +13,8 @@ class CourseReader( fun findAllByDepartmentIdInMajorElective(departmentId: Long): List { return courseRepository.findAllByDepartmentId(departmentId, Classification.MAJOR_ELECTIVE) } + + fun findAllByDepartmentIdInGeneralRequired(departmentId: Long): List { + return courseRepository.findAllByDepartmentId(departmentId, Classification.GENERAL_REQUIRED) + } } diff --git a/src/main/resources/http/course.http b/src/main/resources/http/course.http index ab55707..c7fd5ca 100644 --- a/src/main/resources/http/course.http +++ b/src/main/resources/http/course.http @@ -13,4 +13,10 @@ Content-Type: application/x-www-form-urlencoded ### GET localhost:8080/api/courses/major/elective?schoolId={{schoolId}}&department={{department}}&grade={{grade}} Content-Type: application/x-www-form-urlencoded +### + +// 교양 핈 과목 조회 +### +GET localhost:8080/api/courses/general/required?schoolId={{schoolId}}&department={{department}}&grade={{grade}} +Content-Type: application/x-www-form-urlencoded ### \ No newline at end of file diff --git a/src/test/kotlin/com/yourssu/soongpt/common/support/fixture/CourseFixture.kt b/src/test/kotlin/com/yourssu/soongpt/common/support/fixture/CourseFixture.kt index b9c2a55..478348a 100644 --- a/src/test/kotlin/com/yourssu/soongpt/common/support/fixture/CourseFixture.kt +++ b/src/test/kotlin/com/yourssu/soongpt/common/support/fixture/CourseFixture.kt @@ -23,7 +23,15 @@ enum class CourseFixture( classification = Classification.MAJOR_ELECTIVE, courseCode = 2, credit = 3, - ); + ), + GENERAL_REQUIRED( + courseName = "교양필수", + professorName = "교수명", + classification = Classification.GENERAL_REQUIRED, + courseCode = 3, + credit = 3, + ) + ; fun toDomain(courseCode: Int = this.courseCode): Course { return Course( diff --git a/src/test/kotlin/com/yourssu/soongpt/domain/course/storage/business/CourseServiceTest.kt b/src/test/kotlin/com/yourssu/soongpt/domain/course/storage/business/CourseServiceTest.kt index f1ec315..4abf509 100644 --- a/src/test/kotlin/com/yourssu/soongpt/domain/course/storage/business/CourseServiceTest.kt +++ b/src/test/kotlin/com/yourssu/soongpt/domain/course/storage/business/CourseServiceTest.kt @@ -99,4 +99,36 @@ class CourseServiceTest { } } } + + @Nested + @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores::class) + inner class findByDepartmentNameInGeneralRequired_메서드는 { + @Nested + @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores::class) + inner class 학과를_받으면 { + val departmentName = "소프트웨어학부" + @BeforeEach + fun setUp() { + initializer.run() + val course = courseRepository.save(CourseFixture.GENERAL_REQUIRED.toDomainRandomCourseCode()) + val departmentGrade = jpaQueryFactory.selectFrom(departmentGradeEntity) + .innerJoin(departmentEntity) + .on(departmentGradeEntity.departmentId.eq(departmentEntity.id)) + .where(departmentEntity.name.eq(departmentName), departmentGradeEntity.grade.eq(4)) + .fetchOne() + ?.toDomain() + ?: throw IllegalArgumentException("소프트웨어학부 4학년이 존재하지 않습니다.") + targetRepository.save(Target(departmentGradeId = departmentGrade.id!!, courseId = course.id!!)) + courseTimeRepository.save(CourseTimeFixture.MONDAY_17_19.toDomain(course.id!!)) + } + + @Test + @DisplayName("해당 학과가 수강대상인 과목 정보를 반환한다.") + fun success() { + val response = courseService.findByDepartmentNameInGeneralRequired(departmentName) + + assertEquals(1, response.size) + } + } + } } \ No newline at end of file