Skip to content

Commit d1049b7

Browse files
committed
[#124]; feat: 지원자의 면접 가능시간을 동기화 하는 로직 추가
1 parent 0059626 commit d1049b7

5 files changed

Lines changed: 73 additions & 18 deletions

File tree

src/main/kotlin/com/yourssu/scouter/ats/business/domain/applicant/FormResponseToApplicantProcessor.kt

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,18 @@ import com.yourssu.scouter.common.implement.domain.part.Part
77
import com.yourssu.scouter.common.implement.domain.semester.Semester
88
import com.yourssu.scouter.common.implement.support.google.GoogleFormsReader
99
import com.yourssu.scouter.common.implement.support.google.UserResponse
10-
import org.slf4j.LoggerFactory
10+
import com.yourssu.scouter.common.implement.support.initialization.ApplicantAvailableTimeMap
1111
import org.springframework.stereotype.Component
1212
import java.time.LocalDateTime
13+
import java.time.format.DateTimeFormatter
14+
import java.util.Locale
1315

1416
@Component
1517
class FormResponseToApplicantProcessor(
1618
private val googleFormsReader: GoogleFormsReader,
19+
private val applicantAvailableTimeMap: ApplicantAvailableTimeMap
1720
) {
1821

19-
val logger = LoggerFactory.getLogger(FormResponseToApplicantProcessor::class.java)
20-
2122
fun mapFormResponsesToApplicants(
2223
googleAccessToken: String,
2324
formId: String,
@@ -58,7 +59,7 @@ class FormResponseToApplicantProcessor(
5859
applicationSemester = applicationSemester,
5960
academicSemester = userResponse.getAnswer(question.academicSemesterQuestion) ?: "",
6061
availableTimes = parseResponseToLocalDateTime(
61-
userResponse.getAnswer(question.availableTimeQuestion)
62+
userResponse, question.availableTimeQuestion
6263
),
6364
)
6465

@@ -92,18 +93,35 @@ class FormResponseToApplicantProcessor(
9293
applicationDateTime = userResponse.createTime,
9394
applicationSemester = applicantSyncMapping.applicationSemester,
9495
academicSemester = userResponse.getAnswer(applicantSyncMapping.academicSemesterQuestion) ?: "",
95-
availableTimes = parseResponseToLocalDateTime(
96-
userResponse.getAnswer(applicantSyncMapping.availableTimeQuestion)),
96+
availableTimes = parseResponseToLocalDateTime(userResponse, applicantSyncMapping.availableTimeQuestion),
9797
)
9898

9999
return ApplicantSyncInfo(applicant, applicantSyncMapping.formId, userResponse.responseId)
100100
}
101101

102-
private fun parseResponseToLocalDateTime(availableTimeResponse: String?): List<LocalDateTime> {
103-
if (availableTimeResponse == null) return emptyList()
104-
logger.info("availableTimeResponse: $availableTimeResponse")
105-
return availableTimeResponse.split(",").map { LocalDateTime.parse(it) }
106-
}
102+
private fun parseResponseToLocalDateTime(
103+
userResponse: UserResponse, question: String?
104+
): List<LocalDateTime> =
105+
userResponse.getAll(question).let { responseItems ->
106+
responseItems.flatMap {
107+
if (it.answer == "불가") return@flatMap emptyList()
108+
val days = it.question.substringAfterLast(":")
109+
val times: List<String>? =
110+
if (it.answer == "상관없음") applicantAvailableTimeMap.time.flatMap { (_, value) -> value }
111+
else {
112+
it.answer.split(",").flatMap { time ->
113+
applicantAvailableTimeMap.time[time.trim()] as Iterable<String>
114+
}
115+
}
116+
val year = LocalDateTime.now().year
117+
times?.map { time ->
118+
LocalDateTime.parse(
119+
"$year $days $time",
120+
DateTimeFormatter.ofPattern("yyyy M월 d일 E요일 HH:mm").withLocale(Locale.KOREA)
121+
)
122+
} as Iterable<LocalDateTime>
123+
}
124+
}
107125
}
108126

109127
data class MappingQuestionDto(

src/main/kotlin/com/yourssu/scouter/ats/storage/domain/applicant/ApplicantRepositoryImpl.kt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,16 @@ class ApplicantRepositoryImpl(
2424
}
2525

2626
override fun saveAll(applicants: List<Applicant>) {
27-
jpaAvailableTimeRepository
28-
.saveAll(applicants.map { ApplicantAvailableTimeEntity.from(it) }.flatten())
27+
val savedApplicants = jpaApplicantRepository
28+
.saveAll(applicants.map { ApplicantEntity.from(it) })
29+
val applicantMap = applicants.associateBy { "${it.name}_${it.email}" }
30+
val availableTimeEntities = savedApplicants.flatMap { saved ->
31+
val originalTime = applicantMap["${saved.name}_${saved.email}"]!!.availableTimes
32+
ApplicantAvailableTimeEntity.from(saved.toDomain(originalTime))
33+
}
2934

30-
jpaApplicantRepository.saveAll(applicants.map { ApplicantEntity.from(it) })
35+
jpaAvailableTimeRepository
36+
.saveAll(availableTimeEntities)
3137
}
3238

3339
override fun findById(applicantId: Long): Applicant? {

src/main/kotlin/com/yourssu/scouter/common/implement/support/google/GoogleFormsClient.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,21 @@ data class GoogleFormQuestions(
2828
data class FormItem(
2929
val itemId: String,
3030
val title: String?,
31-
val questionItem: QuestionItem?
31+
val questionItem: QuestionItem?,
32+
val questionGroupItem: QuestionGroupItem?
33+
)
34+
35+
data class QuestionGroupItem(
36+
val questions: List<Questions>?,
37+
)
38+
39+
data class Questions(
40+
val questionId: String,
41+
val rowQuestion: RowQuestion
42+
)
43+
44+
data class RowQuestion(
45+
val title: String
3246
)
3347

3448
data class QuestionItem(

src/main/kotlin/com/yourssu/scouter/common/implement/support/google/GoogleFormsReader.kt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class GoogleFormsReader(
1010
fun getUserResponses(authorizationHeader: String, formId: String): List<UserResponse> {
1111
val questionResponse = googleFormsClient.getFormQuestions(authorizationHeader, formId)
1212
val questionMap: Map<String, String?> = makeQuestionIdAndTitleMap(questionResponse)
13+
val groupQuestionMap: Map<String, String> = getGroupItems(questionResponse)
1314
val formResponses: GoogleFormResponses = googleFormsClient.getFormResponses(authorizationHeader, formId)
1415

1516
return formResponses.responses.map { googleUserResponse ->
@@ -18,7 +19,7 @@ class GoogleFormsReader(
1819
createTime = googleUserResponse.createTime,
1920
respondentEmail = googleUserResponse.respondentEmail,
2021
lastSubmittedTime = googleUserResponse.lastSubmittedTime,
21-
responseItems = convertToResponseItems(googleUserResponse, questionMap)
22+
responseItems = convertToResponseItems(googleUserResponse, questionMap, groupQuestionMap)
2223
)
2324
}
2425
}
@@ -30,12 +31,21 @@ class GoogleFormsReader(
3031
questionId to item.title
3132
}.toMap()
3233

34+
private fun getGroupItems(questionResponse: GoogleFormQuestions) =
35+
questionResponse.items.flatMap { item ->
36+
if (item.questionGroupItem == null) return@flatMap emptyList()
37+
item.questionGroupItem.questions?.map { (questionId, rowQuestion) ->
38+
questionId to item.title + ":" + rowQuestion.title
39+
} as Iterable<Pair<String, String>>
40+
}.associate { it.first to it.second }
41+
3342
private fun convertToResponseItems(
3443
googleUserResponse: GoogleUserResponse,
35-
questionMap: Map<String, String?>
44+
questionMap: Map<String, String?>,
45+
groupQuestionMap: Map<String, String>
3646
): List<ResponseItem> {
3747
val responseItems: List<ResponseItem> = googleUserResponse.answers.mapNotNull { (questionId, answer) ->
38-
val questionTitle = questionMap[questionId] ?: return@mapNotNull null
48+
val questionTitle = questionMap[questionId] ?: groupQuestionMap[questionId] ?: return@mapNotNull null
3949
val answerText = answer.textAnswers?.answers?.joinToString(", ") { it.value.toString() } ?: ""
4050
ResponseItem(questionTitle, answerText)
4151
}

src/main/kotlin/com/yourssu/scouter/common/implement/support/google/UserResponse.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ data class UserResponse(
3030

3131
return responseItems.find { it.question.startsWith(question) }?.answer
3232
}
33+
34+
fun getAll(question: String?): List<ResponseItem> {
35+
if (question == null) {
36+
return emptyList()
37+
}
38+
return responseItems.filter { it.question.startsWith(question) }
39+
}
3340
}
3441

3542
data class ResponseItem(

0 commit comments

Comments
 (0)