-
Notifications
You must be signed in to change notification settings - Fork 0
feature/36-pdf-and-excel-merge-to-application #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6f7b05b
6cf4740
56f7716
8342fca
b10dea7
112e3e4
f3a72d9
8438816
1b73ec4
84e336c
e36be96
e82a35b
49bebaf
31f7f8b
af42b50
2840a88
4b74aa9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,12 @@ | ||||||||||||||||||||||||||||||||||||||
| package hs.kr.entrydsm.domain.status.aggregates | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| import hs.kr.entrydsm.domain.status.values.ApplicationStatus | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| data class StatusCache( | ||||||||||||||||||||||||||||||||||||||
| val receiptCode: Long, | ||||||||||||||||||||||||||||||||||||||
| val examCode: String?, | ||||||||||||||||||||||||||||||||||||||
| val applicationStatus: ApplicationStatus, | ||||||||||||||||||||||||||||||||||||||
| val isFirstRoundPass: Boolean, | ||||||||||||||||||||||||||||||||||||||
| val isSecondRoundPass: Boolean, | ||||||||||||||||||||||||||||||||||||||
| val ttl: Long | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+5
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 단일 소스 유지: applicationStatus와 boolean 동시 보유는 불일치 위험 중복 상태가 서로 엇갈릴 수 있습니다. 선택지:
data class StatusCache(
val receiptCode: Long,
val examCode: String?,
val applicationStatus: ApplicationStatus,
- val isFirstRoundPass: Boolean,
- val isSecondRoundPass: Boolean,
+ @Deprecated("applicationStatus에서 파생됩니다. 차기 버전에서 제거 예정.")
+ val isFirstRoundPass: Boolean,
+ @Deprecated("applicationStatus에서 파생됩니다. 차기 버전에서 제거 예정.")
+ val isSecondRoundPass: Boolean,
val ttl: Long
)원하시면 A안(계산 프로퍼티/함수로 노출)으로 마이그레이션 플랜과 코드까지 드리겠습니다. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| package hs.kr.entrydsm.domain.status.interfaces | ||
|
|
||
| interface ApplicationCommandStatusContract { | ||
| fun updateExamCode(receiptCode: Long, examCode: String) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package hs.kr.entrydsm.domain.status.interfaces | ||
|
|
||
| import hs.kr.entrydsm.domain.status.aggregates.Status | ||
| import hs.kr.entrydsm.domain.status.aggregates.StatusCache | ||
|
|
||
| interface ApplicationQueryStatusContract { | ||
| fun queryStatusByReceiptCode(receiptCode: Long): Status? | ||
| fun queryStatusByReceiptCodeInCache(receiptCode: Long): StatusCache? | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,3 @@ | ||
| package hs.kr.entrydsm.domain.status.interfaces | ||
|
|
||
| interface StatusContract : | ||
| SaveExamCodeContract | ||
| interface StatusContract : ApplicationQueryStatusContract, ApplicationCommandStatusContract |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,24 +1,42 @@ | ||
| package hs.kr.entrydsm.domain.status.values | ||
|
|
||
| /** | ||
| * 지원서 상태를 나타내는 열거형 클래스입니다. | ||
| * gRPC 프로토콜과 매핑되는 지원 상태를 정의합니다. | ||
| */ | ||
| enum class ApplicationStatus { | ||
| /** 미지원 - 지원자가 원서를 작성하지 않은 상태 */ | ||
| /** | ||
| * 미지원 - 지원자가 원서를 작성하지 않은 상태 | ||
| */ | ||
| NOT_APPLIED, | ||
|
|
||
| /** 원서 작성 중 - 원서가 저장되었으나 제출되지 않은 상태 */ | ||
| /** | ||
| * 원서 작성 중 - 원서가 저장되었으나 제출되지 않은 상태 | ||
| */ | ||
| WRITING, | ||
|
|
||
| /** 지원 완료 - 온라인 원서 접수 완료 상태 */ | ||
| /** | ||
| * 지원 완료 - 온라인 원서 접수 완료 상태 | ||
| */ | ||
| SUBMITTED, | ||
|
|
||
| /** 서류 도착 대기 - 원서 제출 후 학교에서 접수 확인 전 상태 */ | ||
| /** | ||
| * 서류 도착 대기 - 원서 제출 후 학교에서 접수 확인 전 상태 | ||
| */ | ||
| WAITING_DOCUMENTS, | ||
|
|
||
| /** 서류 접수 완료 - 학교에서 원서 및 증빙 서류가 정상적으로 도착하여 검토 완료된 상태 */ | ||
| /** | ||
| * 서류 접수 완료 - 학교에서 원서 및 증빙 서류가 정상적으로 도착하여 검토 완료된 상태 | ||
| */ | ||
| DOCUMENTS_RECEIVED, | ||
|
|
||
| /** 전형 진행 중 - 1차 또는 2차 전형이 진행 중인 상태 */ | ||
| /** | ||
| * 전형 진행 중 - 1차 또는 2차 전형이 진행 중인 상태 | ||
| */ | ||
| SCREENING_IN_PROGRESS, | ||
|
|
||
| /** 합격 여부 확인 - 최종 합격자 발표 완료 상태 */ | ||
| RESULT_ANNOUNCED | ||
| /** | ||
| * 합격 여부 확인 - 최종 합격자 발표 완료 상태 | ||
| */ | ||
| RESULT_ANNOUNCED, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package hs.kr.entrydsm.domain.user.aggregates | ||
|
|
||
| import hs.kr.entrydsm.global.annotation.aggregates.Aggregate | ||
| import java.util.UUID | ||
|
|
||
| @Aggregate(context = "user") | ||
| data class User( | ||
| val id: UUID, | ||
| val phoneNumber: String, | ||
| val name: String, | ||
| val isParent: Boolean | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| package hs.kr.entrydsm.domain.user.interfaces | ||
|
|
||
| import hs.kr.entrydsm.domain.user.aggregates.User | ||
| import java.util.UUID | ||
|
|
||
| interface ApplicationQueryUserContract { | ||
| fun queryUserByUserId(userId: UUID): User | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| package hs.kr.entrydsm.domain.user.interfaces | ||
|
|
||
| interface UserContract : ApplicationQueryUserContract { | ||
| } |
This file was deleted.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,47 @@ | ||||||||||||||||||
| package hs.kr.entrydsm.application.domain.status.domain | ||||||||||||||||||
|
|
||||||||||||||||||
| import hs.kr.entrydsm.application.domain.status.domain.repository.StatusCacheRepository | ||||||||||||||||||
| import hs.kr.entrydsm.application.global.grpc.client.status.StatusGrpcClient | ||||||||||||||||||
| import hs.kr.entrydsm.domain.status.aggregates.Status | ||||||||||||||||||
| import hs.kr.entrydsm.domain.status.aggregates.StatusCache | ||||||||||||||||||
| import hs.kr.entrydsm.domain.status.interfaces.StatusContract | ||||||||||||||||||
| import kotlinx.coroutines.runBlocking | ||||||||||||||||||
| import org.springframework.stereotype.Component | ||||||||||||||||||
|
|
||||||||||||||||||
| @Component | ||||||||||||||||||
| class StatusPersistenceAdapter( | ||||||||||||||||||
| private val statusGrpcClient: StatusGrpcClient, | ||||||||||||||||||
| private val statusCacheRepository: StatusCacheRepository | ||||||||||||||||||
| ) : StatusContract { | ||||||||||||||||||
|
|
||||||||||||||||||
| override fun queryStatusByReceiptCode(receiptCode: Long): Status? = runBlocking { | ||||||||||||||||||
| statusGrpcClient.getStatusByReceiptCode(receiptCode)?.let { | ||||||||||||||||||
| Status( | ||||||||||||||||||
| id = it.id, | ||||||||||||||||||
| examCode = it.examCode, | ||||||||||||||||||
| applicationStatus = it.applicationStatus, | ||||||||||||||||||
| isFirstRoundPass = it.isFirstRoundPass, | ||||||||||||||||||
| isSecondRoundPass = it.isSecondRoundPass, | ||||||||||||||||||
| receiptCode = it.receiptCode | ||||||||||||||||||
| ) | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| override fun queryStatusByReceiptCodeInCache(receiptCode: Long): StatusCache? { | ||||||||||||||||||
| return statusCacheRepository.findById(receiptCode) | ||||||||||||||||||
| .map { | ||||||||||||||||||
| StatusCache( | ||||||||||||||||||
| receiptCode = it.receiptCode, | ||||||||||||||||||
| applicationStatus = it.applicationStatus, | ||||||||||||||||||
| examCode = it.examCode, | ||||||||||||||||||
| isFirstRoundPass = it.isFirstRoundPass, | ||||||||||||||||||
| isSecondRoundPass = it.isSecondRoundPass, | ||||||||||||||||||
| ttl = it.ttl | ||||||||||||||||||
| ) | ||||||||||||||||||
| }.orElse(null) | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| override fun updateExamCode(receiptCode: Long, examCode: String) = runBlocking { | ||||||||||||||||||
| statusGrpcClient.updateExamCode(receiptCode, examCode) | ||||||||||||||||||
| } | ||||||||||||||||||
|
Comment on lines
+44
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 캐시 일관성 깨짐 — 시험번호 갱신 후 캐시 무효화/갱신 필요. gRPC로 examCode를 갱신해도 Redis 캐시는 그대로입니다. 이후 조회가 캐시에서 나가면 구값을 돌려줍니다. 최소한 무효화해 주세요. - override fun updateExamCode(receiptCode: Long, examCode: String) = runBlocking {
- statusGrpcClient.updateExamCode(receiptCode, examCode)
- }
+ override fun updateExamCode(receiptCode: Long, examCode: String) = runBlocking {
+ statusGrpcClient.updateExamCode(receiptCode, examCode)
+ // 캐시 일관성 보장: 갱신 직후 캐시 무효화(또는 재적재 로직 선택)
+ statusCacheRepository.deleteById(receiptCode)
+ }📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| } | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package hs.kr.entrydsm.application.domain.status.domain.entity | ||
|
|
||
| import hs.kr.entrydsm.domain.status.values.ApplicationStatus | ||
| import org.springframework.data.annotation.Id | ||
| import org.springframework.data.redis.core.RedisHash | ||
| import org.springframework.data.redis.core.TimeToLive | ||
|
|
||
|
Comment on lines
+4
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 누락된 import 및 TTL 단위 명시
package hs.kr.entrydsm.application.domain.status.domain.entity
@@
+import hs.kr.entrydsm.domain.status.values.ApplicationStatus
import org.springframework.data.annotation.Id
import org.springframework.data.redis.core.RedisHash
import org.springframework.data.redis.core.TimeToLive
+import java.util.concurrent.TimeUnit
@@
- @TimeToLive
+ @TimeToLive(unit = TimeUnit.SECONDS)
val ttl: LongAlso applies to: 12-16 |
||
| @RedisHash("status_cache") | ||
| class StatusCacheRedisEntity( | ||
| @Id | ||
| val receiptCode: Long, | ||
| val examCode: String?, | ||
| val applicationStatus: ApplicationStatus, | ||
| val isFirstRoundPass: Boolean, | ||
| val isSecondRoundPass: Boolean, | ||
| @TimeToLive | ||
| val ttl: Long | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package hs.kr.entrydsm.application.domain.status.domain.repository | ||
|
|
||
| import hs.kr.entrydsm.application.domain.status.domain.entity.StatusCacheRedisEntity | ||
| import org.springframework.data.repository.CrudRepository | ||
|
|
||
| interface StatusCacheRepository : CrudRepository<StatusCacheRedisEntity, Long>{ | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package hs.kr.entrydsm.application.domain.user.domain | ||
|
|
||
| import hs.kr.entrydsm.application.global.grpc.client.user.UserGrpcClient | ||
| import hs.kr.entrydsm.domain.user.aggregates.User | ||
| import hs.kr.entrydsm.domain.user.interfaces.UserContract | ||
| import kotlinx.coroutines.runBlocking | ||
| import org.springframework.stereotype.Component | ||
| import java.util.UUID | ||
|
|
||
| @Component | ||
| class UserPersistenceAdapter( | ||
| private val userGrpcClient: UserGrpcClient | ||
| ) : UserContract { | ||
|
|
||
| override fun queryUserByUserId(userId: UUID): User = runBlocking { | ||
| userGrpcClient.getUserInfoByUserId(userId).run { | ||
| User( | ||
| id = id, | ||
| phoneNumber = phoneNumber, | ||
| name = name, | ||
| isParent = isParent, | ||
| ) | ||
| } | ||
|
|
||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
마이그레이션/호환성 체크 필요
applicationStatus(디폴트 없음) 도입은 직렬화/캐시/GRPC 매핑, 생성 위치 전부의 변경을 요구합니다. 구버전 필드(isSubmitted,isPrintsArrived) 소비자가 외부에 있다면 디프리케이션 기간/변환 계층이 필요합니다.다음 점을 확인해 주세요:
isFirstRoundPass/isSecondRoundPass의 일관성검증을 위한 간단 스크립트입니다:
🏁 Script executed:
Length of output: 116
🏁 Script executed:
Length of output: 3169
Status 생성 위치에 applicationStatus 인자 추가 필요
Status생성 호출부(StatusPersistenceAdapter, ExcelTestController 등)에서applicationStatus인자를 누락해 컴파일 오류가 발생합니다. 모든 호출부에 적절한ApplicationStatus값을 전달하도록 수정하세요.isSubmitted·isPrintsArrived필드 사용 흔적은 없으므로 디프리케이션 계층은 불필요합니다.