feat(application): Application 공통 기반 구성 #24 - #61
Conversation
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
🚫 Excluded labels (none allowed) (2)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 Walkthrough사용자는 지원자 정보 입력, 지원서 관리, 2027년 대덕소프트웨어마이스터고 1차 평가 점수 계산을 위한 공통 기반을 사용할 수 있습니다. 영속성, REST API, 부트스트랩, 데이터베이스 연동은 후속 작업이 필요합니다. 아키텍처 변경
주요 위험 영역
마이그레이션 및 호환성
검증 체크리스트 및 롤아웃
Walkthrough지원자 도메인 모델과 전형 점수 계산을 추가했습니다. 지원서 생성·수정·제출과 학업 기록 저장·평가 결과 계산을 위한 포트, 명령, 결과 타입, 서비스를 구현했습니다. Changes지원자 도메인과 평가 계산
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant ApplicationCommandService
participant ApplicantRepository
participant EvaluationCommandService
participant ScoreCalculator
Client->>ApplicationCommandService: 지원자 생성 및 지원서 갱신
ApplicationCommandService->>ApplicantRepository: 지원자 조회 및 저장
Client->>ApplicationCommandService: 지원서 제출
ApplicationCommandService->>ApplicantRepository: 제출 상태 저장
Client->>EvaluationCommandService: 학업 기록 저장 및 평가 요청
EvaluationCommandService->>ApplicantRepository: 지원자 조회
EvaluationCommandService->>ScoreCalculator: 평가 점수 계산
ScoreCalculator-->>EvaluationCommandService: 전형별 점수
EvaluationCommandService->>ApplicantRepository: 평가 결과 저장
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 8 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (8 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
716731e to
076b14c
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 14
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@systems/application/application-application/deps.bzl`:
- Around line 1-4: Remove the direct
`@maven//`:org_springframework_boot_spring_boot_starter entry from KOTLIN_DEPS in
application-application unless an actual application-layer usage requires it. If
it is required, document the specific usage and architectural exception, and
verify the Spring binding can be moved to an adapter or bootstrap layer.
In
`@systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/ApplicationPort.kt`:
- Line 23: 랜딩 조회가 현재 계정의 지원자 정보를 사용하도록 변경하세요. ApplicationPort.kt 23-23의
getLanding 계약에 accountId를 추가하고, ApplicantRepository.kt 5-8에 accountId 기반 지원자 조회
계약을 정의한 뒤, ApplicationCommandService.kt 93-95에서 해당 조회 결과의 이름을 LandingResult에
반환하세요.
In
`@systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/ApplicationCommandService.kt`:
- Around line 220-228: Applicant 모델에 제출 상태 또는 제출 시각 필드를 추가하고,
ApplicationCommandService.submit()이 검증을 통과한 뒤 해당 값을 updatedAt 변경과 함께 원자적으로 영속하도록
수정하세요. 제출 상태를 기준으로 이후 제출 여부를 판별하고, 제출된 Applicant의 수정 가능 여부도 동일한 상태를 사용해 제한하세요.
- Around line 26-28: Remove the Spring `@Service` annotation and its
org.springframework.stereotype.Service import from ApplicationCommandService,
keeping the class as a framework-independent application service. Register this
service as a bean in the bootstrap configuration instead.
In
`@systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/EvaluationCommandService.kt`:
- Around line 79-94: Move score-range validation from EvaluationCommandService
methods saveGedScores and saveAcademicRecord into init blocks on the GedScores
and AcademicRecord domain models in Applicant.kt. Validate every GED score with
require(value in 0..100), and ensure AcademicRecord’s required fields are
validated there as well, so direct construction and deserialization preserve the
same invariants without relying on the service.
- Around line 137-144: Update the score-key contract between calculateResult and
ScoreCalculator.calculate so the REGULAR score is accessed through a shared,
type-safe symbol rather than a raw string key. Ensure the contract cannot
silently produce null when the key is mismatched, while preserving the existing
totalScore update and applicantRepository.save flow.
- Around line 66-135: Apply a non-read-only `@Transactional` boundary to
saveSubjectGrades, saveGedScores, saveAcademicRecord, and saveCertificates, and
add optimistic locking through the Applicant entity’s version column (or the
project’s established pessimistic-lock mechanism) so concurrent
read-modify-write operations cannot silently overwrite each other. Ensure
getApplicant and the subsequent mutations and save execute within the same
transaction.
- Around line 20-26: Remove the Spring `@Service` annotation and
org.springframework.stereotype.Service import from EvaluationCommandService so
the application layer remains framework-neutral. Change ScoreCalculator from
direct construction to a constructor-injected dependency, update the service
constructor accordingly, and register both ScoreCalculator and
EvaluationCommandService through `@Bean` factory methods in the bootstrap
ApplicationBeanConfiguration, exposing the service as EvaluationPort.
In
`@systems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/model/Applicant.kt`:
- Around line 41-46: Applicant의 createdAt, updatedAt 기본값과 touch()에서 직접 호출하는
LocalDateTime.now()를 제거하고, java.time.Clock 또는 상위 계층에서 결정한 시간 값을 주입하도록 변경하세요.
touch()도 동일한 주입된 시간 소스를 사용해 갱신되도록 하며, 기존 호출자가 필요한 생성자 인자를 제공하도록 Applicant 초기화
경로를 함께 조정하세요.
- Around line 15-47: Applicant과 AcademicRecord를 가변 상태를 포함한 data class로 유지하지 말고
일반 class로 변경하며, 각 엔티티의 id를 기준으로 equals와 hashCode를 구현하세요.
EvaluationCommandService의 제자리 변경 동작은 유지하되, 식별자 기반 동등성이 상태 변경 후에도 안정적으로 동작하도록 관련
생성·갱신 흐름을 함께 조정하세요.
In
`@systems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/service/ScoreCalculator.kt`:
- Around line 14-53: Change ScoreCalculator.calculate to return
Map<AdmissionType, Double> and replace the string keys with AdmissionType
constants. In EvaluationCommandService at
systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/EvaluationCommandService.kt:137-144,
retrieve REGULAR with getValue(AdmissionType.REGULAR), update calculateResult
and EvaluationResult.scores types accordingly, or convert keys with mapKeys {
it.key.name } if the external result must remain Map<String, Double>. In
ScoreCalculator.kt:14-53, apply the corresponding domain-type changes.
- Around line 169-196: Add unit tests for ScoreCalculator covering null
academicRecord returning a zero-score map, all-A complete records reaching the
REGULAR 173 and SOCIAL/MEISTER 119 caps, graduate versus prospective-graduate
semester weights, renormalization when semesters are missing, mutually exclusive
GED and school-grade paths, and attendance boundaries at totals 2, 3, and 5.
Keep the tests in the same application-domain subsystem and use the existing
production constants and fixtures where available.
- Around line 21-29: ScoreCalculator의 gedScores 분기에서 검정고시 지원자의 출결·봉사 점수를 일반
record 필드로 계산하지 않도록 2027학년도 전형 요강의 환산 규칙을 반영하세요. calculateAttendanceScore와
calculateVolunteerScore 호출에 검정고시 전용 처리 또는 적절한 규칙 분기를 추가하고, 일반 학교 지원자의 기존 계산은
유지하세요.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 0ec47915-ee5d-4afb-9c15-f1be49c47445
📒 Files selected for processing (36)
systems/application/application-application/deps.bzlsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/exception/ApplicantNotFoundException.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/ApplicationPort.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/EvaluationPort.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/CalculateEvaluationCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/CreateApplicantCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveAcademicRecordCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveCertificatesCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveGedScoresCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveSubjectGradesCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SubmitApplicationCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateFamilyCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateIntroductionCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateMiddleSchoolCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdatePersonalCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateStudyPlanCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateTypeCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/AcademicRecordResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/CreateApplicantResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/EvaluationResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/LandingResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/out/ApplicantRepository.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/ApplicationCommandService.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/EvaluationCommandService.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/AdmissionType.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/Gender.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/GraduationType.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/GuardianRelation.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/PassResultStatus.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/Region.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/ResultType.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SchoolSemester.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SpecialAdmissionType.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SubjectGrade.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/model/Applicant.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/service/ScoreCalculator.kt
📜 Review details
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{kt,go}
📄 CodeRabbit inference engine (Custom checks)
If production logic is changed in Kotlin or Go files, require corresponding test updates in the same subsystem unless the PR description explicitly justifies why tests are unnecessary
Files:
systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SubmitApplicationCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/LandingResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/out/ApplicantRepository.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateIntroductionCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/CalculateEvaluationCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateStudyPlanCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveGedScoresCommand.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/Region.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/AdmissionType.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/AcademicRecordResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveAcademicRecordCommand.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/GuardianRelation.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateFamilyCommand.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/Gender.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateTypeCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveCertificatesCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdatePersonalCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateMiddleSchoolCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/CreateApplicantCommand.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SubjectGrade.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/EvaluationResult.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SpecialAdmissionType.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/ApplicationPort.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveSubjectGradesCommand.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/PassResultStatus.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/ResultType.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SchoolSemester.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/GraduationType.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/EvaluationPort.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/exception/ApplicantNotFoundException.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/EvaluationCommandService.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/model/Applicant.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/service/ScoreCalculator.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/CreateApplicantResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/ApplicationCommandService.kt
**/*-application/**/*.{java,kt,scala,groovy}
📄 CodeRabbit inference engine (Custom checks)
For files under *-application modules, flag direct dependency on infrastructure-specific framework classes unless justified
Files:
systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SubmitApplicationCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/LandingResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/out/ApplicantRepository.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateIntroductionCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/CalculateEvaluationCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateStudyPlanCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveGedScoresCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/AcademicRecordResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveAcademicRecordCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateFamilyCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateTypeCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveCertificatesCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdatePersonalCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateMiddleSchoolCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/CreateApplicantCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/EvaluationResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/ApplicationPort.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveSubjectGradesCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/EvaluationPort.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/exception/ApplicantNotFoundException.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/EvaluationCommandService.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/CreateApplicantResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/ApplicationCommandService.kt
**/*.{java,kt,scala,groovy,go,js,ts,tsx,jsx,py,rb,rs,cpp,c,h,hpp,cs}
📄 CodeRabbit inference engine (Custom checks)
Flag TODO/FIXME comments introduced by this PR that do not include an issue reference in the form
#123or a full tracker key like PROJ-123
Files:
systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SubmitApplicationCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/LandingResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/out/ApplicantRepository.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateIntroductionCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/CalculateEvaluationCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateStudyPlanCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveGedScoresCommand.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/Region.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/AdmissionType.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/AcademicRecordResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveAcademicRecordCommand.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/GuardianRelation.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateFamilyCommand.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/Gender.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateTypeCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveCertificatesCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdatePersonalCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateMiddleSchoolCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/CreateApplicantCommand.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SubjectGrade.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/EvaluationResult.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SpecialAdmissionType.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/ApplicationPort.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveSubjectGradesCommand.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/PassResultStatus.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/ResultType.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SchoolSemester.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/GraduationType.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/EvaluationPort.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/exception/ApplicantNotFoundException.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/EvaluationCommandService.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/model/Applicant.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/service/ScoreCalculator.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/CreateApplicantResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/ApplicationCommandService.kt
**/*.kt
⚙️ CodeRabbit configuration file
**/*.kt: Apply Kotlin Official Coding Conventions.Formatting and structure:
- Use 4 spaces for indentation; no tabs.
- Keep files focused and readable; avoid horizontal alignment for spacing.
- Place related declarations together and keep overloads adjacent.
- Keep implementation member order stable and logical for readability.
Naming:
- Package names are lowercase and do not use underscores.
- Class/object names use UpperCamelCase.
- Functions/properties/local variables use lowerCamelCase.
- Constants use UPPER_SNAKE_CASE only for true constants.
API and null-safety:
- Avoid platform type leakage in public APIs.
- Use explicit types in public APIs when inference obscures meaning.
- Prefer immutable values (
val) over mutable values (var) unless mutation is required.- Flag nullable flows that can be replaced with safer modeling.
Imports and idioms:
- Avoid wildcard imports unless justified by language/tooling conventions.
- Prefer expression bodies for short, clear functions.
- Prefer standard library idioms over custom utility wrappers when equivalent.
Architecture and tests:
- Respect module boundaries (domain/application/adapter/bootstrap layering).
- Highlight behavior-changing code that lacks corresponding unit/integration tests.
- Ask for deterministic tests and meaningful assertions, not only happy-path checks.
Files:
systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SubmitApplicationCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/LandingResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/out/ApplicantRepository.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateIntroductionCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/CalculateEvaluationCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateStudyPlanCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveGedScoresCommand.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/Region.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/AdmissionType.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/AcademicRecordResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveAcademicRecordCommand.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/GuardianRelation.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateFamilyCommand.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/Gender.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateTypeCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveCertificatesCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdatePersonalCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateMiddleSchoolCommand.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/CreateApplicantCommand.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SubjectGrade.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/EvaluationResult.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SpecialAdmissionType.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/ApplicationPort.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveSubjectGradesCommand.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/PassResultStatus.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/ResultType.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SchoolSemester.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/GraduationType.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/EvaluationPort.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/exception/ApplicantNotFoundException.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/EvaluationCommandService.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/model/Applicant.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/service/ScoreCalculator.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/result/CreateApplicantResult.ktsystems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/ApplicationCommandService.kt
**/{BUILD.bazel,*.bzl}
📄 CodeRabbit inference engine (Custom checks)
In BUILD.bazel and .bzl files, require buildifier-compatible formatting and stable target naming
Files:
systems/application/application-application/deps.bzl
**/*.bzl
⚙️ CodeRabbit configuration file
**/*.bzl: Apply Bazel Starlark (.bzl) style guidance.Readability and docs:
- Keep file/module docstrings and docstrings for public functions/macros.
- Use descriptive parameter names and document attribute intent.
API design:
- Macros should take a
nameargument and derive generated target names from it.- Prefer keyword arguments when calling macros for clarity and stability.
- Keep macro side effects predictable and visible.
Encapsulation:
- Use private visibility for helper targets created by macros unless explicitly public.
- Avoid exposing internal implementation targets unintentionally.
Tooling:
- Enforce buildifier formatting and lint compliance.
Files:
systems/application/application-application/deps.bzl
**/*-domain/**/*.{java,kt,scala,groovy}
📄 CodeRabbit inference engine (Custom checks)
For files under *-domain modules, fail if imports reference adapter or bootstrap packages
Files:
systems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/Region.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/AdmissionType.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/GuardianRelation.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/Gender.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SubjectGrade.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SpecialAdmissionType.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/PassResultStatus.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/ResultType.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SchoolSemester.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/GraduationType.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/model/Applicant.ktsystems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/service/ScoreCalculator.kt
🔇 Additional comments (18)
systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/CalculateEvaluationCommand.kt (1)
3-5: LGTM!systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/CreateApplicantCommand.kt (1)
3-5: LGTM!systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveAcademicRecordCommand.kt (1)
3-10: LGTM!systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveCertificatesCommand.kt (1)
3-7: LGTM!systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveGedScoresCommand.kt (1)
3-8: LGTM!systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SaveSubjectGradesCommand.kt (1)
3-10: LGTM!systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/SubmitApplicationCommand.kt (1)
3-5: LGTM!systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateFamilyCommand.kt (1)
3-15: LGTM!systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/command/UpdateIntroductionCommand.kt (1)
3-6: LGTM!systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/port/in/EvaluationPort.kt (1)
12-15: 🎯 Functional Correctness문제점 없음
EvaluationCommandService가EvaluationPort의 command 객체를 오버라이드하고 내부에서 기존 필드 인자 형태의 메서드를 호출해 시그니처 불일치는 없습니다.systems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/Gender.kt (1)
1-6: LGTM!systems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SchoolSemester.kt (1)
3-8: LGTM!systems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SpecialAdmissionType.kt (1)
3-11: LGTM!systems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/enum/SubjectGrade.kt (1)
3-10: LGTM!systems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/model/Applicant.kt (1)
49-86: LGTM!systems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/service/ScoreCalculator.kt (2)
122-128: 🎯 Functional Correctness | ⚡ Quick win봉사 시간과 일반전형 가산점의 환산 규칙을 확인하세요.
두 가지를 확인해야 합니다.
calculateVolunteerScore는 봉사 시간을 1시간당 1점으로 직접 환산하고 15점에서 자릅니다. 다수 전형 요강은 구간별 환산표를 사용합니다.calculateRegularAdditionalScore는 일반전형에서isProgrammingCertified(6점)를 반영하지 않습니다.calculateSpecialAdditionalScore만 반영합니다. 이 차이가 요강상 의도인지, 누락인지 명시가 필요합니다.두 항목 모두 전형 요강 근거를 주석이나 KDoc으로 남기세요. 근거가 없으면 이후 유지보수에서 회귀가 발생합니다.
55-79: LGTM!Also applies to: 141-167
systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/EvaluationCommandService.kt (1)
28-64: LGTM!Also applies to: 146-153
| KOTLIN_DEPS = [ | ||
| "@maven//:org_springframework_boot_spring_boot_starter", | ||
| "//systems/application/application-domain:main", | ||
| ] |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift
application-application의 Spring Boot 직접 의존성을 제거하거나 정당화하세요.
KOTLIN_DEPS에 spring_boot_starter를 추가하면 application 계층이 Spring API에 직접 결합됩니다. PR 설명은 adapter와 bootstrap을 제외하지만, 이 의존성이 필요한 이유를 설명하지 않습니다. Spring API가 실제로 필요하지 않으면 Line 2를 제거하세요. 필요하면 사용처와 계층 예외를 문서화하고 framework binding을 adapter 또는 bootstrap 계층으로 이동할 수 있는지 확인하세요.
권장 방향
KOTLIN_DEPS = [
- "`@maven//`:org_springframework_boot_spring_boot_starter",
"//systems/application/application-domain:main",
]As per coding guidelines: **/*-application/**/*.{java,kt,scala,groovy} 파일에서는 infrastructure-specific framework 직접 의존성을 정당화해야 합니다.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| KOTLIN_DEPS = [ | |
| "@maven//:org_springframework_boot_spring_boot_starter", | |
| "//systems/application/application-domain:main", | |
| ] | |
| KOTLIN_DEPS = [ | |
| "//systems/application/application-domain:main", | |
| ] |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@systems/application/application-application/deps.bzl` around lines 1 - 4,
Remove the direct `@maven//`:org_springframework_boot_spring_boot_starter entry
from KOTLIN_DEPS in application-application unless an actual application-layer
usage requires it. If it is required, document the specific usage and
architectural exception, and verify the Spring binding can be moved to an
adapter or bootstrap layer.
Source: Coding guidelines
| import org.springframework.stereotype.Service | ||
|
|
||
| @Service |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift
애플리케이션 계층에서 Spring 의존성을 제거해야 합니다.
@Service와 org.springframework.stereotype.Service는 인프라 프레임워크 의존성입니다. 이 서비스는 순수 애플리케이션 서비스로 유지하세요. 빈 등록은 bootstrap 구성으로 이동하세요.
As per coding guidelines, *-application 모듈에서는 정당화되지 않은 인프라 프레임워크 클래스 직접 의존성을 플래그해야 합니다.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/ApplicationCommandService.kt`
around lines 26 - 28, Remove the Spring `@Service` annotation and its
org.springframework.stereotype.Service import from ApplicationCommandService,
keeping the class as a framework-independent application service. Register this
service as a bean in the bootstrap configuration instead.
Source: Coding guidelines
| fun submit(applicantId: Long) { | ||
| val applicant = getApplicant(applicantId) | ||
| require(applicant.admissionType != null) { "admission type is required" } | ||
| require(!applicant.name.isNullOrBlank()) { "personal info is required" } | ||
| require(!applicant.guardianName.isNullOrBlank()) { "family info is required" } | ||
| require(!applicant.introduction.isNullOrBlank()) { "introduction is required" } | ||
| require(!applicant.studyPlan.isNullOrBlank()) { "studyPlan is required" } | ||
| saveTouched(applicant) | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
제출 상태를 영속해야 합니다.
submit()은 검증 후 updatedAt만 변경합니다. 제공된 Applicant 모델에는 제출 상태가 없습니다. 따라서 이후 흐름은 지원서가 제출되었는지 구분할 수 없습니다.
Applicant에 제출 상태 또는 제출 시각을 추가하세요. submit()에서 이를 원자적으로 기록하세요. 제출된 지원서의 수정 가능 여부도 같은 상태로 제어하세요.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/ApplicationCommandService.kt`
around lines 220 - 228, Applicant 모델에 제출 상태 또는 제출 시각 필드를 추가하고,
ApplicationCommandService.submit()이 검증을 통과한 뒤 해당 값을 updatedAt 변경과 함께 원자적으로 영속하도록
수정하세요. 제출 상태를 기준으로 이후 제출 여부를 판별하고, 제출된 Applicant의 수정 가능 여부도 동일한 상태를 사용해 제한하세요.
| import org.springframework.stereotype.Service | ||
|
|
||
| @Service | ||
| class EvaluationCommandService( | ||
| private val applicantRepository: ApplicantRepository, | ||
| ) : EvaluationPort { | ||
| private val scoreCalculator = ScoreCalculator() |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
애플리케이션 계층이 Spring 프레임워크에 직접 의존합니다.
application-application 모듈에서 org.springframework.stereotype.Service를 임포트하고 @Service를 사용합니다. 헥사고날 구조에서 애플리케이션 계층은 프레임워크에 중립이어야 합니다. 빈 등록은 부트스트랩 모듈의 @Configuration에서 @Bean 팩토리 메서드로 처리하세요.
추가로 Line 26에서 ScoreCalculator()를 직접 생성합니다. 이 방식은 테스트에서 계산기를 대체할 수 없게 만들고, 계산기에 의존성이 생기면 변경이 전파됩니다. 생성자 주입으로 바꾸세요.
♻️ 제안 변경
-import java.time.LocalDateTime
-import org.springframework.stereotype.Service
-
-@Service
class EvaluationCommandService(
private val applicantRepository: ApplicantRepository,
+ private val scoreCalculator: ScoreCalculator,
) : EvaluationPort {
- private val scoreCalculator = ScoreCalculator()부트스트랩 모듈에 빈 정의를 추가하세요.
`@Configuration`
class ApplicationBeanConfiguration {
`@Bean`
fun scoreCalculator(): ScoreCalculator = ScoreCalculator()
`@Bean`
fun evaluationCommandService(
applicantRepository: ApplicantRepository,
scoreCalculator: ScoreCalculator,
): EvaluationPort = EvaluationCommandService(applicantRepository, scoreCalculator)
}코딩 가이드라인에 따라 "For files under *-application modules, flag direct dependency on infrastructure-specific framework classes unless justified" 규칙을 적용했습니다.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@systems/application/application-application/src/main/kotlin/hs/kr/entrydsm/application/application/service/EvaluationCommandService.kt`
around lines 20 - 26, Remove the Spring `@Service` annotation and
org.springframework.stereotype.Service import from EvaluationCommandService so
the application layer remains framework-neutral. Change ScoreCalculator from
direct construction to a constructor-injected dependency, update the service
constructor accordingly, and register both ScoreCalculator and
EvaluationCommandService through `@Bean` factory methods in the bootstrap
ApplicationBeanConfiguration, exposing the service as EvaluationPort.
Source: Coding guidelines
| data class Applicant( | ||
| val id: Long, | ||
| val accountId: Long, | ||
| var photoFileId: Long? = null, | ||
| var name: String? = null, | ||
| var phoneNumber: String? = null, | ||
| var gender: Gender? = null, | ||
| var birthdate: LocalDate? = null, | ||
| var specialAdmissionType: SpecialAdmissionType = SpecialAdmissionType.NONE, | ||
| var admissionType: AdmissionType? = null, | ||
| var region: Region? = null, | ||
| var graduationType: GraduationType? = null, | ||
| var graduationDate: YearMonth? = null, | ||
| var guardianName: String? = null, | ||
| var guardianPhoneNumber: String? = null, | ||
| var guardianGender: Gender? = null, | ||
| var guardianRelation: GuardianRelation? = null, | ||
| var addressBase: String? = null, | ||
| var addressDetail: String? = null, | ||
| var zipCode: String? = null, | ||
| var introduction: String? = null, | ||
| var studyPlan: String? = null, | ||
| var middleSchoolInfo: MiddleSchoolInfo? = null, | ||
| var academicRecord: AcademicRecord? = null, | ||
| var totalScore: Double? = null, | ||
| var totalScoreUpdatedAt: LocalDateTime? = null, | ||
| val createdAt: LocalDateTime = LocalDateTime.now(), | ||
| var updatedAt: LocalDateTime = LocalDateTime.now(), | ||
| ) { | ||
| fun touch() { | ||
| updatedAt = LocalDateTime.now() | ||
| } | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift
가변 프로퍼티를 가진 data class의 equals/hashCode 위험을 확인하세요.
Applicant는 data class이며 대부분의 프로퍼티가 var입니다. hashCode가 가변 상태로 계산됩니다. Applicant를 HashSet이나 Map 키로 사용하면, 상태 변경 후 조회가 실패합니다. AcademicRecord도 동일하며 subjectGrades가 MutableMap이라 위험이 더 큽니다.
두 가지 대안이 있습니다.
- 식별자 기반 동등성이 필요하면
data class를 일반class로 바꾸고id기준으로equals/hashCode를 구현하세요. - 값 의미가 필요하면
var를val로 바꾸고copy()로 상태를 갱신하세요.
현재 EvaluationCommandService가 제자리 변경에 의존하므로, 변경 시 서비스 코드도 함께 수정해야 합니다.
경로 지침에 따라 "Prefer immutable values (val) over mutable values (var) unless mutation is required" 규칙을 적용했습니다.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@systems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/model/Applicant.kt`
around lines 15 - 47, Applicant과 AcademicRecord를 가변 상태를 포함한 data class로 유지하지 말고
일반 class로 변경하며, 각 엔티티의 id를 기준으로 equals와 hashCode를 구현하세요.
EvaluationCommandService의 제자리 변경 동작은 유지하되, 식별자 기반 동등성이 상태 변경 후에도 안정적으로 동작하도록 관련
생성·갱신 흐름을 함께 조정하세요.
Source: Path instructions
| val createdAt: LocalDateTime = LocalDateTime.now(), | ||
| var updatedAt: LocalDateTime = LocalDateTime.now(), | ||
| ) { | ||
| fun touch() { | ||
| updatedAt = LocalDateTime.now() | ||
| } |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
시스템 시계 의존을 주입 가능하게 만드세요.
createdAt, updatedAt 기본값과 touch()가 LocalDateTime.now()를 직접 호출합니다. 시간 관련 동작을 결정적으로 테스트할 수 없습니다. java.time.Clock을 주입하거나, 시간 값을 생성자 파라미터로 받아 상위 계층에서 결정하세요.
♻️ 제안 변경
- val createdAt: LocalDateTime = LocalDateTime.now(),
- var updatedAt: LocalDateTime = LocalDateTime.now(),
+ val createdAt: LocalDateTime,
+ var updatedAt: LocalDateTime,
) {
- fun touch() {
- updatedAt = LocalDateTime.now()
+ fun touch(now: LocalDateTime) {
+ updatedAt = now
}
}경로 지침에 따라 "Ask for deterministic tests and meaningful assertions" 규칙을 적용했습니다.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| val createdAt: LocalDateTime = LocalDateTime.now(), | |
| var updatedAt: LocalDateTime = LocalDateTime.now(), | |
| ) { | |
| fun touch() { | |
| updatedAt = LocalDateTime.now() | |
| } | |
| val createdAt: LocalDateTime, | |
| var updatedAt: LocalDateTime, | |
| ) { | |
| fun touch(now: LocalDateTime) { | |
| updatedAt = now | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@systems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/model/Applicant.kt`
around lines 41 - 46, Applicant의 createdAt, updatedAt 기본값과 touch()에서 직접 호출하는
LocalDateTime.now()를 제거하고, java.time.Clock 또는 상위 계층에서 결정한 시간 값을 주입하도록 변경하세요.
touch()도 동일한 주입된 시간 소스를 사용해 갱신되도록 하며, 기존 호출자가 필요한 생성자 인자를 제공하도록 Applicant 초기화
경로를 함께 조정하세요.
Source: Path instructions
| val gedScores = record.gedScores | ||
| val baseSubjectScore = if (gedScores != null) { | ||
| calculateGedBaseScore(gedScores) | ||
| } else { | ||
| calculateSchoolBaseScore(record, applicant.graduationType) | ||
| } | ||
|
|
||
| val attendanceScore = calculateAttendanceScore(record) | ||
| val volunteerScore = calculateVolunteerScore(record.volunteerTime) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
검정고시 지원자의 출결·봉사 점수 처리를 확인하세요.
gedScores가 있으면 교과 점수만 검정고시 기준으로 계산합니다. 그러나 attendanceScore와 volunteerScore는 동일한 record 필드로 계산합니다(Line 28-29). 검정고시 지원자는 중학교 출결·봉사 기록이 없으므로 absentCount 등이 기본값 0으로 남습니다. 그 결과 출결은 자동 만점 15점, 봉사는 자동 0점이 됩니다. 봉사 0점은 검정고시 지원자에게 일방적으로 불리합니다.
2027학년도 전형 요강에서 검정고시 지원자의 출결·봉사 영역 환산 규칙을 확인하고, 필요하면 별도 분기를 추가하세요.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@systems/application/application-domain/src/main/kotlin/hs/kr/entrydsm/application/domain/service/ScoreCalculator.kt`
around lines 21 - 29, ScoreCalculator의 gedScores 분기에서 검정고시 지원자의 출결·봉사 점수를 일반
record 필드로 계산하지 않도록 2027학년도 전형 요강의 환산 규칙을 반영하세요. calculateAttendanceScore와
calculateVolunteerScore 호출에 검정고시 전용 처리 또는 적절한 규칙 분기를 추가하고, 일반 학교 지원자의 기존 계산은
유지하세요.
b174f6c to
4e21930
Compare
6befa27 to
6e47778
Compare
Summary
원서작성 및 성적산출 기능의 공통 domain/application 기반을 구성했습니다.
지원자 모델, 지원 전형/지역/졸업 구분/합격 결과 enum을 추가했습니다.
2027학년도 대덕소프트웨어마이스터고 1차 전형 성적 산출 로직을 도메인 서비스로 구성했습니다.
원서작성과 성적산출 API에서 사용할 input/output port, command/result, application service를 정의했습니다.
Related Issue
Related to #24
Scope
In scope:
Out of scope:
Implementation
Applicant 모델에 지원자 기본 정보, 보호자 정보, 주소, 자기소개서/학업계획서, 성적 정보를 구성했습니다.
ScoreCalculator는 2027학년도 전형 요강 기준으로 내신, 출결, 봉사, 가산점 기반 1차 전형 점수를 계산합니다.
ApplicationService는 지원서 생성, 조회, 수정 흐름을 담당합니다.
EvaluationService는 지원자의 성적 정보를 기반으로 전형별 산출 결과를 반환합니다.
저장소는 ApplicantRepository port로만 정의하고 실제 구현은 후속 PR에서 연결합니다.
Testing
Deployment Notes
Feature flag: 없음
Migration required: 없음
Rollout considerations:
Checklist