Skip to content

Commit 7301714

Browse files
committed
service 분리 및 최근 과목 수정
1 parent 1e6d62d commit 7301714

File tree

6 files changed

+117
-66
lines changed

6 files changed

+117
-66
lines changed
Lines changed: 19 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,39 @@
11
package com.wafflestudio.snu4t.handler
22

3-
import com.fasterxml.jackson.databind.ObjectMapper
4-
import com.wafflestudio.snu4t.config.SnuttEvWebClient
5-
import com.wafflestudio.snu4t.coursebook.service.CoursebookService
6-
import com.wafflestudio.snu4t.evaluation.dto.EvLectureInfoDto
3+
import com.wafflestudio.snu4t.evaluation.service.EvService
74
import com.wafflestudio.snu4t.middleware.SnuttRestApiDefaultMiddleware
8-
import com.wafflestudio.snu4t.timetables.service.TimetableService
9-
import kotlinx.coroutines.flow.toList
10-
import org.springframework.http.HttpHeaders
115
import org.springframework.http.HttpMethod
12-
import org.springframework.http.MediaType
136
import org.springframework.stereotype.Component
14-
import org.springframework.web.reactive.function.BodyInserters
15-
import org.springframework.web.reactive.function.client.awaitBody
167
import org.springframework.web.reactive.function.server.ServerRequest
178
import org.springframework.web.reactive.function.server.awaitBody
18-
import org.springframework.web.util.UriComponentsBuilder
19-
import java.net.URLEncoder
209

2110
@Component
2211
class EvServiceHandler(
23-
private val coursebookService: CoursebookService,
24-
private val timetableService: TimetableService,
25-
private val snuttEvWebClient: SnuttEvWebClient,
12+
private val evService: EvService,
2613
snuttRestApiDefaultMiddleware: SnuttRestApiDefaultMiddleware,
2714
) : ServiceHandler(snuttRestApiDefaultMiddleware) {
28-
suspend fun handleGet(req: ServerRequest) = handleRouting(req, HttpMethod.GET)
29-
30-
suspend fun handlePost(req: ServerRequest) = handleRouting(req, HttpMethod.POST)
31-
32-
suspend fun handleDelete(req: ServerRequest) = handleRouting(req, HttpMethod.DELETE)
15+
suspend fun handleGet(req: ServerRequest) =
16+
handle(req) {
17+
evService.handleRouting(req.userId, req.pathVariable("requestPath"), req.queryParams(), req.awaitBody(), HttpMethod.GET)
18+
}
3319

34-
suspend fun handlePatch(req: ServerRequest) = handleRouting(req, HttpMethod.PATCH)
20+
suspend fun handlePost(req: ServerRequest) =
21+
handle(req) {
22+
evService.handleRouting(req.userId, req.pathVariable("requestPath"), req.queryParams(), req.awaitBody(), HttpMethod.POST)
23+
}
3524

36-
private suspend fun handleRouting(
37-
req: ServerRequest,
38-
method: HttpMethod,
39-
) = handle(req) {
40-
val userId = req.userId
41-
val requestPath = req.pathVariable("requestPath")
42-
val originalBody = req.awaitBody<String>()
25+
suspend fun handleDelete(req: ServerRequest) =
26+
handle(req) {
27+
evService.handleRouting(req.userId, req.pathVariable("requestPath"), req.queryParams(), req.awaitBody(), HttpMethod.DELETE)
28+
}
4329

44-
snuttEvWebClient.method(method)
45-
.uri { builder -> builder.path("/v1").path(requestPath).build() }
46-
.header("Snutt-User-Id", userId)
47-
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
48-
.body(BodyInserters.fromValue(originalBody))
49-
.retrieve()
50-
.awaitBody()
51-
}
30+
suspend fun handlePatch(req: ServerRequest) =
31+
handle(req) {
32+
evService.handleRouting(req.userId, req.pathVariable("requestPath"), req.queryParams(), req.awaitBody(), HttpMethod.PATCH)
33+
}
5234

5335
suspend fun getMyLatestLectures(req: ServerRequest) =
5436
handle(req) {
55-
val userId = req.userId
56-
val requestQueryParams = req.queryParams()
57-
val recentLectures =
58-
coursebookService.getLastTwoCourseBooks().flatMap { coursebook ->
59-
timetableService.getTimetablesBySemester(userId, coursebook.year, coursebook.semester)
60-
.toList()
61-
.flatMap {
62-
timetable ->
63-
timetable.lectures.map { lecture -> EvLectureInfoDto(lecture, coursebook.year, coursebook.semester) }
64-
}
65-
}
66-
val recentLecturesJson = ObjectMapper().writeValueAsString(recentLectures).filterNot { it.isWhitespace() }
67-
val encodedJson = URLEncoder.encode(recentLecturesJson, "EUC-KR")
68-
69-
snuttEvWebClient.get()
70-
.uri { builder ->
71-
UriComponentsBuilder.fromUri(builder.build())
72-
.path("/v1/users/me/lectures/latest")
73-
.queryParam("snutt_lecture_info", encodedJson)
74-
.queryParams(requestQueryParams)
75-
.build(true).toUri()
76-
}
77-
.header("Snutt-User-Id", userId)
78-
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
79-
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
80-
.retrieve()
81-
.awaitBody()
37+
evService.getMyLatestLectures(req.userId, req.queryParams())
8238
}
8339
}

api/src/test/kotlin/timetable/TimetableIntegTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.wafflestudio.snu4t.timetable
33
import BaseIntegTest
44
import com.ninjasquad.springmockk.MockkBean
55
import com.wafflestudio.snu4t.evaluation.repository.SnuttEvRepository
6+
import com.wafflestudio.snu4t.evaluation.service.EvService
67
import com.wafflestudio.snu4t.fixture.TimetableFixture
78
import com.wafflestudio.snu4t.fixture.UserFixture
89
import com.wafflestudio.snu4t.handler.RequestContext
@@ -25,6 +26,7 @@ import timetables.dto.TimetableBriefDto
2526
class TimetableIntegTest(
2627
@MockkBean private val mockMiddleware: SnuttRestApiDefaultMiddleware,
2728
@MockkBean private val mockSnuttEvRepository: SnuttEvRepository,
29+
@MockkBean private val evService: EvService,
2830
val mainRouter: MainRouter,
2931
val timetableFixture: TimetableFixture,
3032
val userFixture: UserFixture,

core/src/main/kotlin/coursebook/repository/CoursebookRepository.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ interface CoursebookRepository : CoroutineCrudRepository<Coursebook, String> {
1010

1111
suspend fun findAllByOrderByYearDescSemesterDesc(): List<Coursebook>
1212

13-
suspend fun findTop2ByOrderByYearDescSemesterDesc(): List<Coursebook>
13+
suspend fun findTop3ByOrderByYearDescSemesterDesc(): List<Coursebook>
1414
}

core/src/main/kotlin/coursebook/service/CoursebookService.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ interface CoursebookService {
99

1010
suspend fun getCoursebooks(): List<Coursebook>
1111

12-
suspend fun getLastTwoCourseBooks(): List<Coursebook>
12+
suspend fun getLastTwoCourseBooksBeforeCurrent(): List<Coursebook>
1313
}
1414

1515
@Service
@@ -18,5 +18,8 @@ class CoursebookServiceImpl(private val coursebookRepository: CoursebookReposito
1818

1919
override suspend fun getCoursebooks(): List<Coursebook> = coursebookRepository.findAllByOrderByYearDescSemesterDesc()
2020

21-
override suspend fun getLastTwoCourseBooks(): List<Coursebook> = coursebookRepository.findTop2ByOrderByYearDescSemesterDesc()
21+
override suspend fun getLastTwoCourseBooksBeforeCurrent(): List<Coursebook> =
22+
coursebookRepository.findTop3ByOrderByYearDescSemesterDesc().slice(
23+
1..2,
24+
)
2225
}

core/src/main/kotlin/evaluation/dto/EvLectureInfoDto.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package com.wafflestudio.snu4t.evaluation.dto
22

3+
import com.fasterxml.jackson.annotation.JsonProperty
34
import com.wafflestudio.snu4t.common.enum.Semester
45
import com.wafflestudio.snu4t.timetables.data.TimetableLecture
56

67
data class EvLectureInfoDto(
78
val year: Int,
89
val semester: Int,
910
val instructor: String?,
11+
@JsonProperty("course_number")
1012
val courseNumber: String?,
1113
)
1214

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package com.wafflestudio.snu4t.evaluation.service
2+
3+
import com.fasterxml.jackson.databind.ObjectMapper
4+
import com.fasterxml.jackson.databind.PropertyNamingStrategies
5+
import com.wafflestudio.snu4t.common.util.buildMultiValueMap
6+
import com.wafflestudio.snu4t.config.SnuttEvWebClient
7+
import com.wafflestudio.snu4t.coursebook.service.CoursebookService
8+
import com.wafflestudio.snu4t.evaluation.dto.EvLectureInfoDto
9+
import com.wafflestudio.snu4t.timetables.service.TimetableService
10+
import kotlinx.coroutines.Dispatchers
11+
import kotlinx.coroutines.flow.toList
12+
import kotlinx.coroutines.withContext
13+
import org.springframework.beans.factory.annotation.Qualifier
14+
import org.springframework.http.HttpHeaders
15+
import org.springframework.http.HttpMethod
16+
import org.springframework.http.MediaType
17+
import org.springframework.stereotype.Service
18+
import org.springframework.util.MultiValueMap
19+
import org.springframework.web.reactive.function.BodyInserters
20+
import org.springframework.web.reactive.function.client.awaitBody
21+
import org.springframework.web.util.UriComponentsBuilder
22+
import java.net.URLEncoder
23+
24+
@Service
25+
class EvService(
26+
@Qualifier("snuttevServer")
27+
private val snuttEvWebClient: SnuttEvWebClient,
28+
private val timetableService: TimetableService,
29+
private val coursebookService: CoursebookService,
30+
) {
31+
suspend fun handleRouting(
32+
userId: String,
33+
requestPath: String,
34+
requestQueryParams: MultiValueMap<String, String> = buildMultiValueMap(mapOf()),
35+
originalBody: String,
36+
method: HttpMethod,
37+
): Map<String, Any> =
38+
snuttEvWebClient.method(method)
39+
.uri { builder -> builder.path("/v1").path(requestPath).queryParams(requestQueryParams).build() }
40+
.header("Snutt-User-Id", userId)
41+
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
42+
.body(BodyInserters.fromValue(originalBody))
43+
.retrieve()
44+
.awaitBody()
45+
46+
suspend fun getMyLatestLectures(
47+
userId: String,
48+
requestQueryParams: MultiValueMap<String, String>? = null,
49+
): Map<String, Any> {
50+
val recentLectures: List<EvLectureInfoDto> =
51+
coursebookService.getLastTwoCourseBooksBeforeCurrent().flatMap { coursebook ->
52+
timetableService.getTimetablesBySemester(userId, coursebook.year, coursebook.semester)
53+
.toList()
54+
.flatMap { timetable ->
55+
timetable.lectures.map { lecture ->
56+
EvLectureInfoDto(
57+
lecture,
58+
coursebook.year,
59+
coursebook.semester,
60+
)
61+
}
62+
}
63+
}
64+
65+
val recentLecturesJson =
66+
ObjectMapper().setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
67+
.writeValueAsString(recentLectures)
68+
val encodedJson =
69+
withContext(Dispatchers.IO) {
70+
URLEncoder.encode(recentLecturesJson, "UTF-8")
71+
}
72+
73+
return snuttEvWebClient.get()
74+
.uri { builder ->
75+
UriComponentsBuilder.fromUri(builder.build())
76+
.path("/v1/users/me/lectures/latest")
77+
.queryParam("snutt_lecture_info", encodedJson)
78+
.queryParams(requestQueryParams)
79+
.build(true).toUri()
80+
}
81+
.header("Snutt-User-Id", userId)
82+
.header(HttpHeaders.CONTENT_ENCODING, "UTF-8")
83+
.header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
84+
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
85+
.retrieve()
86+
.awaitBody()
87+
}
88+
}

0 commit comments

Comments
 (0)