From f63c26ebba9afba808331be6ee56e6ebb636da7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Sun, 21 Sep 2025 18:46:45 +0900 Subject: [PATCH 01/16] feat ( #51 ) : contract --- .../application/interfaces/ApplicationContract.kt | 8 ++++++-- .../interfaces/ApplicationPdfGeneratorContract.kt | 7 +++++++ .../interfaces/IntroductionPdfGeneratorContract.kt | 7 +++++++ .../domain/school/interfaces/QuerySchoolContract.kt | 10 +++++++++- 4 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/application/interfaces/ApplicationPdfGeneratorContract.kt create mode 100644 casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/application/interfaces/IntroductionPdfGeneratorContract.kt diff --git a/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/application/interfaces/ApplicationContract.kt b/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/application/interfaces/ApplicationContract.kt index 9a11b5fe..14b75019 100644 --- a/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/application/interfaces/ApplicationContract.kt +++ b/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/application/interfaces/ApplicationContract.kt @@ -1,4 +1,8 @@ package hs.kr.entrydsm.domain.application.interfaces -interface ApplicationContract : - QueryAllFirstRoundPassedApplicationContract \ No newline at end of file +import hs.kr.entrydsm.domain.application.aggregates.Application +import java.util.UUID + +interface ApplicationContract : QueryAllFirstRoundPassedApplicationContract { + fun getApplicationByUserId(userId: UUID): Application? +} \ No newline at end of file diff --git a/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/application/interfaces/ApplicationPdfGeneratorContract.kt b/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/application/interfaces/ApplicationPdfGeneratorContract.kt new file mode 100644 index 00000000..86b683f4 --- /dev/null +++ b/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/application/interfaces/ApplicationPdfGeneratorContract.kt @@ -0,0 +1,7 @@ +package hs.kr.entrydsm.domain.application.interfaces + +import hs.kr.entrydsm.domain.application.aggregates.Application + +interface ApplicationPdfGeneratorContract { + fun generate(application: Application, score: Any): ByteArray +} diff --git a/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/application/interfaces/IntroductionPdfGeneratorContract.kt b/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/application/interfaces/IntroductionPdfGeneratorContract.kt new file mode 100644 index 00000000..06b76a52 --- /dev/null +++ b/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/application/interfaces/IntroductionPdfGeneratorContract.kt @@ -0,0 +1,7 @@ +package hs.kr.entrydsm.domain.application.interfaces + +import hs.kr.entrydsm.domain.application.aggregates.Application + +interface IntroductionPdfGeneratorContract { + fun generate(applications: List): ByteArray +} diff --git a/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/school/interfaces/QuerySchoolContract.kt b/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/school/interfaces/QuerySchoolContract.kt index 231517db..0102073a 100644 --- a/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/school/interfaces/QuerySchoolContract.kt +++ b/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/school/interfaces/QuerySchoolContract.kt @@ -21,4 +21,12 @@ interface QuerySchoolContract { * @return 학교 정보 */ fun querySchoolBySchoolCode(schoolCode: String): School? -} \ No newline at end of file + + /** + * 여러 학교 코드로 학교 목록을 조회합니다. + * + * @param schoolCodes 학교 코드 목록 + * @return 학교 정보 목록 + */ + fun querySchoolsByCodes(schoolCodes: List): List +} From d84de096a870f22c422e0bc83b447fcbcf8a239b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Sun, 21 Sep 2025 18:47:01 +0900 Subject: [PATCH 02/16] feat ( #51 ) : swagger --- .../global/document/admin/AdminApiDocument.kt | 23 +++++++ .../global/document/excel/ExcelApiDocument.kt | 64 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/excel/ExcelApiDocument.kt diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/admin/AdminApiDocument.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/admin/AdminApiDocument.kt index 692ec81f..924bf5af 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/admin/AdminApiDocument.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/admin/AdminApiDocument.kt @@ -14,6 +14,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.RequestBody +import jakarta.servlet.http.HttpServletResponse /** * 어드민 관련 API 문서화를 위한 인터페이스입니다. @@ -21,6 +22,28 @@ import org.springframework.web.bind.annotation.RequestBody @Tag(name = "어드민 API", description = "어드민 관련 API") interface AdminApiDocument { + @Operation(summary = "자기소개서 PDF 조회", description = "1차 합격자들의 자기소개서를 하나의 PDF로 조회합니다.") + @ApiResponses( + value = [ + ApiResponse( + responseCode = "200", + description = "자기소개서 PDF 생성 성공", + content = [ + Content( + mediaType = "application/pdf", + schema = Schema(type = "string", format = "binary") + ) + ] + ), + ApiResponse( + responseCode = "500", + description = "PDF 생성 실패", + content = [Content(schema = Schema(hidden = true))] + ) + ] + ) + fun getIntroductionPdf(response: HttpServletResponse): ResponseEntity + @Operation(summary = "전형 타입 생성", description = "새로운 전형 타입을 생성합니다.") @ApiResponses( value = [ diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/excel/ExcelApiDocument.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/excel/ExcelApiDocument.kt new file mode 100644 index 00000000..b647e567 --- /dev/null +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/excel/ExcelApiDocument.kt @@ -0,0 +1,64 @@ +package hs.kr.entrydsm.application.global.document.excel + +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.responses.ApiResponse +import io.swagger.v3.oas.annotations.responses.ApiResponses +import io.swagger.v3.oas.annotations.tags.Tag +import jakarta.servlet.http.HttpServletResponse + +@Tag(name = "Excel", description = "Excel 파일 출력 API") +interface ExcelApiDocument { + + @Operation( + summary = "수험표 출력", + description = "제출된 모든 지원서를 기반으로 수험표 Excel 파일을 생성하여 다운로드합니다. " + + "각 지원자의 수험번호, 이름, 학교명, 지역, 전형유형, 접수번호와 사진이 포함됩니다." + ) + @ApiResponses( + value = [ + ApiResponse(responseCode = "200", description = "수험표 Excel 파일 다운로드 성공"), + ApiResponse(responseCode = "500", description = "Excel 파일 생성 중 오류 발생") + ] + ) + fun printAdmissionTicket(response: HttpServletResponse) + + @Operation( + summary = "1차 합격자 번호 목록 출력", + description = "1차 전형을 통과한 지원자들의 수험번호, 접수번호, 성명이 포함된 " + + "지원자번호목록 Excel 파일을 생성하여 다운로드합니다." + ) + @ApiResponses( + value = [ + ApiResponse(responseCode = "200", description = "지원자번호목록 Excel 파일 다운로드 성공"), + ApiResponse(responseCode = "404", description = "1차 합격자가 없음"), + ApiResponse(responseCode = "500", description = "Excel 파일 생성 중 오류 발생") + ] + ) + suspend fun printApplicantCodes(response: HttpServletResponse) + + @Operation( + summary = "전형자료 출력", + description = "제출된 모든 지원서의 상세 정보를 포함한 전형자료 Excel 파일을 생성하여 다운로드합니다. " + + "60개 컬럼으로 구성되며 개인정보, 성적, 출석, 봉사활동, 가산점 등 모든 정보가 포함됩니다." + ) + @ApiResponses( + value = [ + ApiResponse(responseCode = "200", description = "전형자료 Excel 파일 다운로드 성공"), + ApiResponse(responseCode = "500", description = "Excel 파일 생성 중 오류 발생") + ] + ) + fun printApplicationInfo(response: HttpServletResponse) + + @Operation( + summary = "지원서 점검표 출력", + description = "제출된 모든 지원서의 점검용 Excel 파일을 생성하여 다운로드합니다. " + + "각 지원자당 20행의 구조화된 점검표가 생성되며, 개인정보와 성적 확인이 가능합니다." + ) + @ApiResponses( + value = [ + ApiResponse(responseCode = "200", description = "점검표 Excel 파일 다운로드 성공"), + ApiResponse(responseCode = "500", description = "Excel 파일 생성 중 오류 발생") + ] + ) + fun printApplicationCheckList(response: HttpServletResponse) +} From a1b0e1423114935b425a78f1b4a717ed1e4bad89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Sun, 21 Sep 2025 18:47:28 +0900 Subject: [PATCH 03/16] refactor ( #51 ) : generate --- .../global/document/pdf/generator/ApplicationPdfGenerator.kt | 5 +++-- .../document/pdf/generator/IntroductionPdfGenerator.kt | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/ApplicationPdfGenerator.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/ApplicationPdfGenerator.kt index 2b93fd18..c607e256 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/ApplicationPdfGenerator.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/ApplicationPdfGenerator.kt @@ -8,6 +8,7 @@ import hs.kr.entrydsm.application.global.document.pdf.data.PdfDataConverter import hs.kr.entrydsm.application.global.document.pdf.data.TemplateFileName import hs.kr.entrydsm.application.global.document.pdf.facade.PdfDocumentFacade import hs.kr.entrydsm.domain.application.aggregates.Application +import hs.kr.entrydsm.domain.application.interfaces.ApplicationPdfGeneratorContract import hs.kr.entrydsm.domain.application.values.ApplicationType import org.springframework.stereotype.Component import java.io.ByteArrayOutputStream @@ -26,7 +27,7 @@ class ApplicationPdfGenerator( private val pdfDataConverter: PdfDataConverter, private val templateProcessor: TemplateProcessor, private val pdfDocumentFacade: PdfDocumentFacade, -) { +) : ApplicationPdfGeneratorContract { /** * 지원서 PDF를 생성합니다. * @@ -34,7 +35,7 @@ class ApplicationPdfGenerator( * @param score Score 도메인 (현재 더미값 사용) * @return 생성된 PDF 바이트 배열 */ - fun generate( + override fun generate( application: Application, score: Any, // TODO: Score 도메인이 없어서 더미값 사용 ): ByteArray { diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/IntroductionPdfGenerator.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/IntroductionPdfGenerator.kt index 7a6031c7..f1f98054 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/IntroductionPdfGenerator.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/IntroductionPdfGenerator.kt @@ -7,6 +7,7 @@ import hs.kr.entrydsm.application.global.document.pdf.data.IntroductionPdfConver import hs.kr.entrydsm.application.global.document.pdf.data.TemplateFileName import hs.kr.entrydsm.application.global.document.pdf.facade.PdfDocumentFacade import hs.kr.entrydsm.domain.application.aggregates.Application +import hs.kr.entrydsm.domain.application.interfaces.IntroductionPdfGeneratorContract import org.springframework.stereotype.Component import java.io.ByteArrayOutputStream import kotlin.collections.toMap @@ -24,14 +25,14 @@ class IntroductionPdfGenerator( private val introductionPdfConverter: IntroductionPdfConverter, private val templateProcessor: TemplateProcessor, private val pdfDocumentFacade: PdfDocumentFacade, -) { +) : IntroductionPdfGeneratorContract { /** * 소개서 PDF를 생성합니다. * * @param applicationList 지원서 목록 (1차 합격자) * @return 생성된 소개서 PDF 바이트 배열 */ - fun generate(applicationList: List): ByteArray { + override fun generate(applicationList: List): ByteArray { val outputStream = ByteArrayOutputStream() val mergedDocument = PdfDocument(PdfWriter(outputStream)) val pdfMerger = PdfMerger(mergedDocument) From a3ca2ac5056ee55e91762b04566ebe44b1a7840e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Sun, 21 Sep 2025 18:47:49 +0900 Subject: [PATCH 04/16] feat ( #51 ) : persistence adapter --- .../domain/school/domain/SchoolPersistenceAdapter.kt | 12 ++++++++++++ .../domain/status/domain/StatusPersistenceAdapter.kt | 12 ++++++++++++ .../domain/user/domain/UserPersistenceAdapter.kt | 12 ++++++++++++ 3 files changed, 36 insertions(+) diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/school/domain/SchoolPersistenceAdapter.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/school/domain/SchoolPersistenceAdapter.kt index 1e96c521..b9aad8d7 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/school/domain/SchoolPersistenceAdapter.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/school/domain/SchoolPersistenceAdapter.kt @@ -85,6 +85,18 @@ class SchoolPersistenceAdapter( } ?: emptyList() } + /** + * 여러 학교 코드로 학교 목록을 조회합니다. + * + * @param schoolCodes 학교 코드 목록 + * @return 학교 정보 목록 + */ + override fun querySchoolsByCodes(schoolCodes: List): List { + return schoolCodes.mapNotNull { schoolCode -> + querySchoolBySchoolCode(schoolCode) + } + } + /** * 학교 정보를 캐시에 저장합니다. * diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/status/domain/StatusPersistenceAdapter.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/status/domain/StatusPersistenceAdapter.kt index 420e80bc..6ddb9035 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/status/domain/StatusPersistenceAdapter.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/status/domain/StatusPersistenceAdapter.kt @@ -45,6 +45,18 @@ class StatusPersistenceAdapter( } } + /** + * 여러 접수번호로 원서 상태 목록을 조회합니다. + * + * @param receiptCodes 조회할 접수번호 목록 + * @return 조회된 상태 정보 목록 + */ + override fun queryStatusesByReceiptCodes(receiptCodes: List): List { + return receiptCodes.mapNotNull { receiptCode -> + queryStatusByReceiptCode(receiptCode) + } + } + /** * 캐시에서 접수번호로 원서 상태를 조회합니다. * diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/user/domain/UserPersistenceAdapter.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/user/domain/UserPersistenceAdapter.kt index a2857893..3e46dcdc 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/user/domain/UserPersistenceAdapter.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/user/domain/UserPersistenceAdapter.kt @@ -37,4 +37,16 @@ class UserPersistenceAdapter( ) } } + + /** + * 여러 사용자 ID로 사용자 정보 목록을 조회합니다. + * + * @param userIds 조회할 사용자들의 고유 식별자 목록 + * @return 조회된 사용자 정보 목록 + */ + override fun queryUsersByIds(userIds: List): List { + return userIds.map { userId -> + queryUserByUserId(userId) + } + } } From 0283beb6f541afc5dab16b67334ee461df556a46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Sun, 21 Sep 2025 18:48:28 +0900 Subject: [PATCH 05/16] feat ( #51 ) : usecase --- .../usecase/PrintAdmissionTicketUseCase.kt | 37 ++++++++++++++++ .../usecase/PrintApplicantCodesUseCase.kt | 22 ++++++++++ .../PrintApplicationCheckListUseCase.kt | 37 ++++++++++++++++ .../usecase/PrintApplicationInfoUseCase.kt | 37 ++++++++++++++++ .../presentation/WebApplicationPdfAdapter.kt | 40 +++++++++++++++++ .../usecase/GetFinalApplicationPdfUseCase.kt | 43 +++++++++++++++++++ .../pdf/usecase/GetIntroductionPdfUseCase.kt | 17 ++++++++ .../GetPreviewApplicationPdfUseCase.kt | 36 ++++++++++++++++ 8 files changed, 269 insertions(+) create mode 100644 casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintAdmissionTicketUseCase.kt create mode 100644 casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintApplicantCodesUseCase.kt create mode 100644 casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintApplicationCheckListUseCase.kt create mode 100644 casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintApplicationInfoUseCase.kt create mode 100644 casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/presentation/WebApplicationPdfAdapter.kt create mode 100644 casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetFinalApplicationPdfUseCase.kt create mode 100644 casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetIntroductionPdfUseCase.kt create mode 100644 casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetPreviewApplicationPdfUseCase.kt diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintAdmissionTicketUseCase.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintAdmissionTicketUseCase.kt new file mode 100644 index 00000000..74957813 --- /dev/null +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintAdmissionTicketUseCase.kt @@ -0,0 +1,37 @@ +package hs.kr.entrydsm.application.domain.excel.usecase + +import hs.kr.entrydsm.application.domain.application.domain.ApplicationPersistenceAdapter +import hs.kr.entrydsm.application.global.excel.generator.PrintAdmissionTicketGenerator +import hs.kr.entrydsm.domain.school.interfaces.SchoolContract +import hs.kr.entrydsm.domain.status.interfaces.ApplicationQueryStatusContract +import hs.kr.entrydsm.domain.user.interfaces.ApplicationQueryUserContract +import org.springframework.stereotype.Service +import jakarta.servlet.http.HttpServletResponse + +@Service +class PrintAdmissionTicketUseCase( + private val printAdmissionTicketGenerator: PrintAdmissionTicketGenerator, + private val applicationPersistenceAdapter: ApplicationPersistenceAdapter, + private val schoolContract: SchoolContract, + private val applicationQueryStatusContract: ApplicationQueryStatusContract, + private val applicationQueryUserContract: ApplicationQueryUserContract +) { + fun execute(httpServletResponse: HttpServletResponse) { + val applications = applicationPersistenceAdapter.querySubmittedApplications() + val receiptCodes = applications.map { it.receiptCode } + val userIds = applications.map { it.userId } + val schoolCodes = applications.mapNotNull { it.schoolCode }.distinct() + + val users = applicationQueryUserContract.queryUsersByIds(userIds) + val schools = schoolContract.querySchoolsByCodes(schoolCodes) + val statuses = applicationQueryStatusContract.queryStatusesByReceiptCodes(receiptCodes) + + printAdmissionTicketGenerator.execute( + response = httpServletResponse, + applications = applications, + users = users, + schools = schools, + statuses = statuses + ) + } +} diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintApplicantCodesUseCase.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintApplicantCodesUseCase.kt new file mode 100644 index 00000000..586c4b8e --- /dev/null +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintApplicantCodesUseCase.kt @@ -0,0 +1,22 @@ +package hs.kr.entrydsm.application.domain.excel.usecase + +import hs.kr.entrydsm.application.global.excel.generator.PrintApplicantCodesGenerator +import hs.kr.entrydsm.domain.application.interfaces.QueryAllFirstRoundPassedApplicationContract +import hs.kr.entrydsm.domain.status.interfaces.ApplicationQueryStatusContract +import org.springframework.stereotype.Service +import jakarta.servlet.http.HttpServletResponse + +@Service +class PrintApplicantCodesUseCase( + private val printApplicantCodesGenerator: PrintApplicantCodesGenerator, + private val queryAllFirstRoundPassedApplicationContract: QueryAllFirstRoundPassedApplicationContract, + private val applicationQueryStatusContract: ApplicationQueryStatusContract +) { + suspend fun execute(httpServletResponse: HttpServletResponse) { + val applications = queryAllFirstRoundPassedApplicationContract.queryAllFirstRoundPassedApplication() + val receiptCodes = applications.map { it.receiptCode } + val statuses = applicationQueryStatusContract.queryStatusesByReceiptCodes(receiptCodes) + + printApplicantCodesGenerator.execute(httpServletResponse, applications, statuses) + } +} diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintApplicationCheckListUseCase.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintApplicationCheckListUseCase.kt new file mode 100644 index 00000000..425d075e --- /dev/null +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintApplicationCheckListUseCase.kt @@ -0,0 +1,37 @@ +package hs.kr.entrydsm.application.domain.excel.usecase + +import hs.kr.entrydsm.application.domain.application.domain.ApplicationPersistenceAdapter +import hs.kr.entrydsm.application.global.excel.generator.PrintApplicationCheckListGenerator +import hs.kr.entrydsm.domain.school.interfaces.SchoolContract +import hs.kr.entrydsm.domain.status.interfaces.ApplicationQueryStatusContract +import hs.kr.entrydsm.domain.user.interfaces.ApplicationQueryUserContract +import org.springframework.stereotype.Service +import jakarta.servlet.http.HttpServletResponse + +@Service +class PrintApplicationCheckListUseCase( + private val printApplicationCheckListGenerator: PrintApplicationCheckListGenerator, + private val applicationPersistenceAdapter: ApplicationPersistenceAdapter, + private val schoolContract: SchoolContract, + private val applicationQueryStatusContract: ApplicationQueryStatusContract, + private val applicationQueryUserContract: ApplicationQueryUserContract +) { + fun execute(httpServletResponse: HttpServletResponse) { + val applications = applicationPersistenceAdapter.querySubmittedApplications() + val receiptCodes = applications.map { it.receiptCode } + val userIds = applications.map { it.userId } + val schoolCodes = applications.mapNotNull { it.schoolCode }.distinct() + + val users = applicationQueryUserContract.queryUsersByIds(userIds) + val schools = schoolContract.querySchoolsByCodes(schoolCodes) + val statuses = applicationQueryStatusContract.queryStatusesByReceiptCodes(receiptCodes) + + printApplicationCheckListGenerator.printApplicationCheckList( + applications = applications, + users = users, + schools = schools, + statuses = statuses, + httpServletResponse = httpServletResponse + ) + } +} diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintApplicationInfoUseCase.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintApplicationInfoUseCase.kt new file mode 100644 index 00000000..418d9409 --- /dev/null +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/usecase/PrintApplicationInfoUseCase.kt @@ -0,0 +1,37 @@ +package hs.kr.entrydsm.application.domain.excel.usecase + +import hs.kr.entrydsm.application.domain.application.domain.ApplicationPersistenceAdapter +import hs.kr.entrydsm.application.global.excel.generator.PrintApplicationInfoGenerator +import hs.kr.entrydsm.domain.school.interfaces.SchoolContract +import hs.kr.entrydsm.domain.status.interfaces.ApplicationQueryStatusContract +import hs.kr.entrydsm.domain.user.interfaces.ApplicationQueryUserContract +import org.springframework.stereotype.Service +import jakarta.servlet.http.HttpServletResponse + +@Service +class PrintApplicationInfoUseCase( + private val printApplicationInfoGenerator: PrintApplicationInfoGenerator, + private val applicationPersistenceAdapter: ApplicationPersistenceAdapter, + private val schoolContract: SchoolContract, + private val applicationQueryStatusContract: ApplicationQueryStatusContract, + private val applicationQueryUserContract: ApplicationQueryUserContract +) { + fun execute(httpServletResponse: HttpServletResponse) { + val applications = applicationPersistenceAdapter.querySubmittedApplications() + val receiptCodes = applications.map { it.receiptCode } + val userIds = applications.map { it.userId } + val schoolCodes = applications.mapNotNull { it.schoolCode }.distinct() + + val users = applicationQueryUserContract.queryUsersByIds(userIds) + val schools = schoolContract.querySchoolsByCodes(schoolCodes) + val statuses = applicationQueryStatusContract.queryStatusesByReceiptCodes(receiptCodes) + + printApplicationInfoGenerator.execute( + httpServletResponse = httpServletResponse, + applications = applications, + users = users, + schools = schools, + statuses = statuses + ) + } +} diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/presentation/WebApplicationPdfAdapter.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/presentation/WebApplicationPdfAdapter.kt new file mode 100644 index 00000000..763fc28a --- /dev/null +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/presentation/WebApplicationPdfAdapter.kt @@ -0,0 +1,40 @@ +package hs.kr.entrydsm.application.domain.pdf.presentation + +import hs.kr.entrydsm.application.domain.pdf.usecase.GetFinalApplicationPdfUseCase +import hs.kr.entrydsm.application.domain.pdf.usecase.GetPreviewApplicationPdfUseCase +import hs.kr.entrydsm.application.global.document.pdf.PdfApiDocument +import org.springframework.http.HttpHeaders +import org.springframework.http.MediaType +import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController +import jakarta.servlet.http.HttpServletResponse + +@RestController +@RequestMapping("/api/v1/application/pdf") +class WebApplicationPdfAdapter( + private val getFinalApplicationPdfUseCase: GetFinalApplicationPdfUseCase, + private val getPreviewApplicationPdfUseCase: GetPreviewApplicationPdfUseCase +) : PdfApiDocument { + + @GetMapping("/preview") + override fun previewPdf(): ResponseEntity { + val pdfBytes = getPreviewApplicationPdfUseCase.execute() + + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PDF_VALUE) + .body(pdfBytes) + } + + @GetMapping("/final") + override fun finalPdf(response: HttpServletResponse): ResponseEntity { + val pdfBytes = getFinalApplicationPdfUseCase.execute() + + response.setHeader("Content-Disposition", "attachment; filename=final_application.pdf") + + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PDF_VALUE) + .body(pdfBytes) + } +} diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetFinalApplicationPdfUseCase.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetFinalApplicationPdfUseCase.kt new file mode 100644 index 00000000..adeb8075 --- /dev/null +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetFinalApplicationPdfUseCase.kt @@ -0,0 +1,43 @@ +package hs.kr.entrydsm.application.domain.pdf.usecase + +import hs.kr.entrydsm.application.global.annotation.usecase.ReadOnlyUseCase +import hs.kr.entrydsm.domain.application.interfaces.ApplicationContract +import hs.kr.entrydsm.domain.application.interfaces.ApplicationPdfGeneratorContract +import hs.kr.entrydsm.domain.score.interfaces.ScoreContract +import hs.kr.entrydsm.domain.security.interfaces.SecurityContract +import hs.kr.entrydsm.domain.status.interfaces.ApplicationQueryStatusContract + +@ReadOnlyUseCase +class GetFinalApplicationPdfUseCase( + private val securityContract: SecurityContract, + private val applicationContract: ApplicationContract, + private val scoreContract: ScoreContract, + private val applicationPdfGeneratorContract: ApplicationPdfGeneratorContract, + private val applicationQueryStatusContract: ApplicationQueryStatusContract +) { + + fun execute(): ByteArray { + val userId = securityContract.getCurrentUserId() + + val application = applicationContract.getApplicationByUserId(userId) + ?: throw IllegalStateException("원서 정보를 찾을 수 없습니다") + + val status = applicationQueryStatusContract.getStatusByReceiptCode(application.receiptCode) + ?: throw IllegalStateException("상태 정보를 찾을 수 없습니다") + + if (!status.isSubmitted) { + throw IllegalStateException("제출되지 않은 원서입니다") + } + + validatePrintableApplication(application) + + // TODO: Score Contract 구현 후 실제 점수 조회 + val score = Any() // 임시 더미 객체 + + return applicationPdfGeneratorContract.generate(application, score) + } + + private fun validatePrintableApplication(application: Any) { + // TODO: 교육 상태 검증 로직 구현 + } +} diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetIntroductionPdfUseCase.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetIntroductionPdfUseCase.kt new file mode 100644 index 00000000..32955db3 --- /dev/null +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetIntroductionPdfUseCase.kt @@ -0,0 +1,17 @@ +package hs.kr.entrydsm.application.domain.pdf.usecase + +import hs.kr.entrydsm.application.global.annotation.usecase.ReadOnlyUseCase +import hs.kr.entrydsm.domain.application.interfaces.IntroductionPdfGeneratorContract +import hs.kr.entrydsm.domain.application.interfaces.QueryAllFirstRoundPassedApplicationContract + +@ReadOnlyUseCase +class GetIntroductionPdfUseCase( + private val queryAllFirstRoundPassedApplicationContract: QueryAllFirstRoundPassedApplicationContract, + private val introductionPdfGeneratorContract: IntroductionPdfGeneratorContract +) { + + suspend fun execute(): ByteArray { + val applications = queryAllFirstRoundPassedApplicationContract.queryAllFirstRoundPassedApplication() + return introductionPdfGeneratorContract.generate(applications) + } +} diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetPreviewApplicationPdfUseCase.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetPreviewApplicationPdfUseCase.kt new file mode 100644 index 00000000..f4847543 --- /dev/null +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetPreviewApplicationPdfUseCase.kt @@ -0,0 +1,36 @@ +package hs.kr.entrydsm.application.domain.pdf.usecase + +import hs.kr.entrydsm.application.global.annotation.usecase.ReadOnlyUseCase +import hs.kr.entrydsm.domain.application.interfaces.ApplicationContract +import hs.kr.entrydsm.domain.application.interfaces.ApplicationPdfGeneratorContract +import hs.kr.entrydsm.domain.score.interfaces.ScoreContract +import hs.kr.entrydsm.domain.security.interfaces.SecurityContract +import hs.kr.entrydsm.domain.status.interfaces.ApplicationQueryStatusContract + +@ReadOnlyUseCase +class GetPreviewApplicationPdfUseCase( + private val securityContract: SecurityContract, + private val applicationContract: ApplicationContract, + private val scoreContract: ScoreContract, + private val applicationPdfGeneratorContract: ApplicationPdfGeneratorContract, + private val applicationQueryStatusContract: ApplicationQueryStatusContract +) { + + fun execute(): ByteArray { + val userId = securityContract.getCurrentUserId() + + val application = applicationContract.getApplicationByUserId(userId) + ?: throw IllegalStateException("원서 정보를 찾을 수 없습니다") + + validatePrintableApplication(application) + + // TODO: Score Contract 구현 후 실제 점수 조회 + val score = Any() // 임시 더미 객체 + + return applicationPdfGeneratorContract.generate(application, score) + } + + private fun validatePrintableApplication(application: Any) { + // TODO: 교육 상태 검증 로직 구현 + } +} From 595b9d649f6e3ed328d42db4bca317e479e8b8aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Sun, 21 Sep 2025 18:48:46 +0900 Subject: [PATCH 06/16] refactor ( #51 ) : swagger --- .../global/document/pdf/PdfApiDocument.kt | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/PdfApiDocument.kt diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/PdfApiDocument.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/PdfApiDocument.kt new file mode 100644 index 00000000..72eb0cc6 --- /dev/null +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/PdfApiDocument.kt @@ -0,0 +1,68 @@ +package hs.kr.entrydsm.application.global.document.pdf + +import io.swagger.v3.oas.annotations.Operation +import io.swagger.v3.oas.annotations.media.Content +import io.swagger.v3.oas.annotations.media.Schema +import io.swagger.v3.oas.annotations.responses.ApiResponse +import io.swagger.v3.oas.annotations.responses.ApiResponses +import io.swagger.v3.oas.annotations.tags.Tag +import org.springframework.http.ResponseEntity + +@Tag(name = "PDF API", description = "원서 PDF 관련 API") +interface PdfApiDocument { + + @Operation(summary = "원서 미리보기 PDF 조회", description = "작성 중인 원서의 미리보기 PDF를 조회합니다.") + @ApiResponses( + value = [ + ApiResponse( + responseCode = "200", + description = "PDF 생성 성공", + content = [ + Content( + mediaType = "application/pdf", + schema = Schema(type = "string", format = "binary") + ) + ] + ), + ApiResponse( + responseCode = "400", + description = "원서 정보를 찾을 수 없음", + content = [Content()] + ), + ApiResponse( + responseCode = "500", + description = "PDF 생성 실패", + content = [Content()] + ) + ] + ) + fun previewPdf(): ResponseEntity + + @Operation(summary = "최종 원서 PDF 조회", description = "제출된 원서의 최종 PDF를 조회합니다.") + @ApiResponses( + value = [ + ApiResponse( + responseCode = "200", + description = "PDF 생성 성공", + content = [ + Content( + mediaType = "application/pdf", + schema = Schema(type = "string", format = "binary") + ) + ] + ), + ApiResponse( + responseCode = "400", + description = "원서 정보를 찾을 수 없거나 제출되지 않은 원서", + content = [Content()] + ), + ApiResponse( + responseCode = "500", + description = "PDF 생성 실패", + content = [Content()] + ) + ] + ) + fun finalPdf(response: jakarta.servlet.http.HttpServletResponse): ResponseEntity + +} From 99bcdba1bfbfd2445aab2328d05e63b07cd9c034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Sun, 21 Sep 2025 18:49:04 +0900 Subject: [PATCH 07/16] feat ( #51 ) : controller --- .../admin/presentation/AdminController.kt | 24 +++++++++++ .../excel/presentation/ExcelController.kt | 41 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/presentation/ExcelController.kt diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/admin/presentation/AdminController.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/admin/presentation/AdminController.kt index c060b19f..1d437497 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/admin/presentation/AdminController.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/admin/presentation/AdminController.kt @@ -7,18 +7,42 @@ import hs.kr.entrydsm.application.domain.admin.presentation.dto.response.CreateA import hs.kr.entrydsm.application.domain.admin.presentation.dto.response.CreateEducationalStatusResponse import hs.kr.entrydsm.application.domain.admin.presentation.dto.response.CreatePrototypeResponse import hs.kr.entrydsm.application.domain.admin.usecase.AdminUseCase +import hs.kr.entrydsm.application.domain.pdf.usecase.GetIntroductionPdfUseCase import hs.kr.entrydsm.application.global.document.admin.AdminApiDocument +import org.springframework.http.HttpHeaders +import org.springframework.http.MediaType import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController +import java.nio.charset.StandardCharsets +import jakarta.servlet.http.HttpServletResponse @RestController @RequestMapping("/api/v1/admin") class AdminController( private val adminUseCase: AdminUseCase, + private val getIntroductionPdfUseCase: GetIntroductionPdfUseCase ) : AdminApiDocument { + + @GetMapping("/pdf/introduction", produces = [MediaType.APPLICATION_PDF_VALUE]) + override fun getIntroductionPdf(response: HttpServletResponse): ResponseEntity { + val pdfBytes = getIntroductionPdfUseCase.execute() + + response.setHeader("Content-Disposition", "attachment; filename=\"${encodeFileName()}.pdf\"") + + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PDF_VALUE) + .body(pdfBytes) + } + + private fun encodeFileName(): String { + val fileName = "introduction" + return String(fileName.toByteArray(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1) + } + @PostMapping("/application-types") override fun createApplicationType( @RequestBody request: CreateApplicationTypeRequest, diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/presentation/ExcelController.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/presentation/ExcelController.kt new file mode 100644 index 00000000..ec8a9f84 --- /dev/null +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/presentation/ExcelController.kt @@ -0,0 +1,41 @@ +package hs.kr.entrydsm.application.domain.excel.presentation + +import hs.kr.entrydsm.application.domain.excel.usecase.PrintAdmissionTicketUseCase +import hs.kr.entrydsm.application.domain.excel.usecase.PrintApplicantCodesUseCase +import hs.kr.entrydsm.application.domain.excel.usecase.PrintApplicationCheckListUseCase +import hs.kr.entrydsm.application.domain.excel.usecase.PrintApplicationInfoUseCase +import hs.kr.entrydsm.application.global.document.excel.ExcelApiDocument +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController +import jakarta.servlet.http.HttpServletResponse + +@RestController +@RequestMapping("/admin/excel") +class WebExcelAdapter( + private val printAdmissionTicketUseCase: PrintAdmissionTicketUseCase, + private val printApplicantCodesUseCase: PrintApplicantCodesUseCase, + private val printApplicationInfoUseCase: PrintApplicationInfoUseCase, + private val printApplicationCheckListUseCase: PrintApplicationCheckListUseCase +) : ExcelApiDocument { + + @GetMapping("/admission-ticket") + override fun printAdmissionTicket(response: HttpServletResponse) { + printAdmissionTicketUseCase.execute(response) + } + + @GetMapping("/applicant-codes") + override suspend fun printApplicantCodes(response: HttpServletResponse) { + printApplicantCodesUseCase.execute(response) + } + + @GetMapping("/application-info") + override fun printApplicationInfo(response: HttpServletResponse) { + printApplicationInfoUseCase.execute(response) + } + + @GetMapping("/check-list") + override fun printApplicationCheckList(response: HttpServletResponse) { + printApplicationCheckListUseCase.execute(response) + } +} From 3c67e939159f9249628e8a8d663b94de010fc0d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Sun, 21 Sep 2025 18:49:19 +0900 Subject: [PATCH 08/16] refactor ( #51) : contract --- .../interfaces/ApplicationQueryStatusContract.kt | 16 ++++++++++++++++ .../interfaces/ApplicationQueryUserContract.kt | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/status/interfaces/ApplicationQueryStatusContract.kt b/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/status/interfaces/ApplicationQueryStatusContract.kt index e9ef04c3..bdf15120 100644 --- a/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/status/interfaces/ApplicationQueryStatusContract.kt +++ b/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/status/interfaces/ApplicationQueryStatusContract.kt @@ -21,6 +21,22 @@ interface ApplicationQueryStatusContract { */ fun queryStatusByReceiptCode(receiptCode: Long): Status? + /** + * 접수번호로 원서 상태를 조회합니다. (getStatusByReceiptCode의 별칭) + * + * @param receiptCode 조회할 접수번호 + * @return 조회된 상태 정보, 존재하지 않는 경우 null + */ + fun getStatusByReceiptCode(receiptCode: Long): Status? = queryStatusByReceiptCode(receiptCode) + + /** + * 여러 접수번호로 원서 상태 목록을 조회합니다. + * + * @param receiptCodes 조회할 접수번호 목록 + * @return 조회된 상태 정보 목록 + */ + fun queryStatusesByReceiptCodes(receiptCodes: List): List + /** * 캐시에서 접수번호로 원서 상태를 조회합니다. * diff --git a/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/user/interfaces/ApplicationQueryUserContract.kt b/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/user/interfaces/ApplicationQueryUserContract.kt index bd170f49..28f22e25 100644 --- a/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/user/interfaces/ApplicationQueryUserContract.kt +++ b/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/user/interfaces/ApplicationQueryUserContract.kt @@ -16,4 +16,12 @@ interface ApplicationQueryUserContract { * @return 조회된 사용자 정보 */ fun queryUserByUserId(userId: UUID): User + + /** + * 여러 사용자 ID로 사용자 정보 목록을 조회합니다. + * + * @param userIds 조회할 사용자들의 고유 식별자 목록 + * @return 조회된 사용자 정보 목록 + */ + fun queryUsersByIds(userIds: List): List } From 8626e9ad67496e71fd673bf6e122b1a965fe700d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Sun, 21 Sep 2025 18:49:38 +0900 Subject: [PATCH 09/16] feat ( #51 ) : persistence adapter --- .../domain/ApplicationPersistenceAdapter.kt | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/application/domain/ApplicationPersistenceAdapter.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/application/domain/ApplicationPersistenceAdapter.kt index 8ddf31ee..c31be3b0 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/application/domain/ApplicationPersistenceAdapter.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/application/domain/ApplicationPersistenceAdapter.kt @@ -7,6 +7,7 @@ import hs.kr.entrydsm.domain.application.interfaces.ApplicationContract import hs.kr.entrydsm.domain.status.interfaces.StatusContract import kotlinx.coroutines.runBlocking import org.springframework.stereotype.Component +import java.util.UUID /** * Application 도메인의 퍼시스턴스 어댑터입니다. @@ -20,6 +21,19 @@ class ApplicationPersistenceAdapter( private val applicationMapper: ApplicationMapper, private val statusContract: StatusContract, ) : ApplicationContract { + + /** + * 사용자 ID로 원서 정보를 조회합니다. + * + * @param userId 사용자 ID + * @return 해당 사용자의 원서 정보, 없으면 null + */ + override fun getApplicationByUserId(userId: UUID): Application? { + return applicationJpaRepository.findAllByUserId(userId) + .firstOrNull() + ?.let { applicationMapper.toModel(it) } + } + /** * 1차 전형 합격 Application을 모두 조회합니다. * @@ -41,4 +55,14 @@ class ApplicationPersistenceAdapter( } } } + + /** + * 제출된 모든 원서를 조회합니다. + * + * @return 제출된 모든 원서 목록 + */ + fun querySubmittedApplications(): List { + return applicationJpaRepository.findAll() + .map { applicationMapper.toModel(it) } + } } From 493311659218e35e802265045bb8c229c862c1c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Sun, 21 Sep 2025 18:49:51 +0900 Subject: [PATCH 10/16] feat ( #51 ) : add method --- .../hs/kr/entrydsm/domain/status/aggregates/Status.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/status/aggregates/Status.kt b/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/status/aggregates/Status.kt index 1a276d74..2432fe97 100644 --- a/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/status/aggregates/Status.kt +++ b/casper-application-domain/src/main/kotlin/hs/kr/entrydsm/domain/status/aggregates/Status.kt @@ -24,4 +24,12 @@ data class Status( val isFirstRoundPass: Boolean = false, val isSecondRoundPass: Boolean = false, val receiptCode: Long, -) +) { + /** + * 원서가 제출되었는지 여부를 확인합니다. + * SUBMITTED 이상의 상태일 때 제출된 것으로 간주합니다. + */ + val isSubmitted: Boolean + get() = applicationStatus != ApplicationStatus.NOT_APPLIED && + applicationStatus != ApplicationStatus.WRITING +} From d1739ec5475903815cb1312d1cbad9b4ac029a43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Sun, 21 Sep 2025 18:53:46 +0900 Subject: [PATCH 11/16] =?UTF-8?q?chore=20(=20#51=20)=20:=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pdf/config/ConverterPropertiesCreator.kt | 2 +- .../application/global/{document => }/pdf/config/Font.kt | 2 +- .../global/{document => }/pdf/config/PdfConfig.kt | 2 +- .../{document => }/pdf/data/IntroductionPdfConverter.kt | 2 +- .../global/{document => }/pdf/data/PdfData.kt | 2 +- .../global/{document => }/pdf/data/PdfDataConverter.kt | 2 +- .../global/{document => }/pdf/data/TemplateFileName.kt | 2 +- .../{document => }/pdf/facade/PdfDocumentFacade.kt | 2 +- .../pdf/generator/ApplicationPdfGenerator.kt | 8 ++++---- .../pdf/generator/IntroductionPdfGenerator.kt | 9 ++++----- .../global/{document => }/pdf/generator/PdfProcessor.kt | 4 ++-- .../{document => }/pdf/generator/TemplateProcessor.kt | 2 +- .../{document => }/pdf/presentation/PdfTestController.kt | 6 +++--- 13 files changed, 22 insertions(+), 23 deletions(-) rename casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/{document => }/pdf/config/ConverterPropertiesCreator.kt (96%) rename casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/{document => }/pdf/config/Font.kt (91%) rename casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/{document => }/pdf/config/PdfConfig.kt (95%) rename casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/{document => }/pdf/data/IntroductionPdfConverter.kt (97%) rename casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/{document => }/pdf/data/PdfData.kt (94%) rename casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/{document => }/pdf/data/PdfDataConverter.kt (99%) rename casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/{document => }/pdf/data/TemplateFileName.kt (94%) rename casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/{document => }/pdf/facade/PdfDocumentFacade.kt (89%) rename casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/{document => }/pdf/generator/ApplicationPdfGenerator.kt (92%) rename casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/{document => }/pdf/generator/IntroductionPdfGenerator.kt (87%) rename casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/{document => }/pdf/generator/PdfProcessor.kt (87%) rename casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/{document => }/pdf/generator/TemplateProcessor.kt (93%) rename casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/{document => }/pdf/presentation/PdfTestController.kt (94%) diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/config/ConverterPropertiesCreator.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/config/ConverterPropertiesCreator.kt similarity index 96% rename from casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/config/ConverterPropertiesCreator.kt rename to casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/config/ConverterPropertiesCreator.kt index fc20d546..25ae21b6 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/config/ConverterPropertiesCreator.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/config/ConverterPropertiesCreator.kt @@ -1,4 +1,4 @@ -package hs.kr.entrydsm.application.global.document.pdf.config +package hs.kr.entrydsm.application.global.pdf.config import com.itextpdf.html2pdf.ConverterProperties import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/config/Font.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/config/Font.kt similarity index 91% rename from casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/config/Font.kt rename to casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/config/Font.kt index 92bcdb1f..3fd33409 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/config/Font.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/config/Font.kt @@ -1,4 +1,4 @@ -package hs.kr.entrydsm.application.global.document.pdf.config +package hs.kr.entrydsm.application.global.pdf.config /** * PDF 생성 시 사용할 폰트 설정을 관리하는 객체입니다. diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/config/PdfConfig.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/config/PdfConfig.kt similarity index 95% rename from casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/config/PdfConfig.kt rename to casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/config/PdfConfig.kt index ec4f6a61..f3f35710 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/config/PdfConfig.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/config/PdfConfig.kt @@ -1,4 +1,4 @@ -package hs.kr.entrydsm.application.global.document.pdf.config +package hs.kr.entrydsm.application.global.pdf.config import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/data/IntroductionPdfConverter.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/IntroductionPdfConverter.kt similarity index 97% rename from casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/data/IntroductionPdfConverter.kt rename to casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/IntroductionPdfConverter.kt index dc72f948..d0751008 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/data/IntroductionPdfConverter.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/IntroductionPdfConverter.kt @@ -1,4 +1,4 @@ -package hs.kr.entrydsm.application.global.document.pdf.data +package hs.kr.entrydsm.application.global.pdf.data import hs.kr.entrydsm.domain.application.aggregates.Application import hs.kr.entrydsm.domain.school.interfaces.QuerySchoolContract diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/data/PdfData.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/PdfData.kt similarity index 94% rename from casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/data/PdfData.kt rename to casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/PdfData.kt index d88082a0..33bce32c 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/data/PdfData.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/PdfData.kt @@ -1,4 +1,4 @@ -package hs.kr.entrydsm.application.global.document.pdf.data +package hs.kr.entrydsm.application.global.pdf.data /** * PDF 템플릿에서 사용할 데이터를 담는 클래스입니다. diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/data/PdfDataConverter.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/PdfDataConverter.kt similarity index 99% rename from casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/data/PdfDataConverter.kt rename to casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/PdfDataConverter.kt index 090544ab..6b9f2e0a 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/data/PdfDataConverter.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/PdfDataConverter.kt @@ -1,4 +1,4 @@ -package hs.kr.entrydsm.application.global.document.pdf.data +package hs.kr.entrydsm.application.global.pdf.data import hs.kr.entrydsm.domain.application.aggregates.Application import hs.kr.entrydsm.domain.application.values.ApplicationType diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/data/TemplateFileName.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/TemplateFileName.kt similarity index 94% rename from casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/data/TemplateFileName.kt rename to casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/TemplateFileName.kt index b7d3fc35..d79d6ec2 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/data/TemplateFileName.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/TemplateFileName.kt @@ -1,4 +1,4 @@ -package hs.kr.entrydsm.application.global.document.pdf.data +package hs.kr.entrydsm.application.global.pdf.data /** * PDF 생성에 사용되는 템플릿 파일명을 정의하는 객체입니다. diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/facade/PdfDocumentFacade.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/facade/PdfDocumentFacade.kt similarity index 89% rename from casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/facade/PdfDocumentFacade.kt rename to casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/facade/PdfDocumentFacade.kt index d260c02c..82910591 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/facade/PdfDocumentFacade.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/facade/PdfDocumentFacade.kt @@ -1,4 +1,4 @@ -package hs.kr.entrydsm.application.global.document.pdf.facade +package hs.kr.entrydsm.application.global.pdf.facade import com.itextpdf.kernel.pdf.PdfDocument import com.itextpdf.kernel.pdf.PdfReader diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/ApplicationPdfGenerator.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/ApplicationPdfGenerator.kt similarity index 92% rename from casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/ApplicationPdfGenerator.kt rename to casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/ApplicationPdfGenerator.kt index c607e256..27446c1e 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/ApplicationPdfGenerator.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/ApplicationPdfGenerator.kt @@ -1,12 +1,12 @@ -package hs.kr.entrydsm.application.global.document.pdf.generator +package hs.kr.entrydsm.application.global.pdf.generator import com.itextpdf.kernel.pdf.PdfDocument import com.itextpdf.kernel.pdf.PdfWriter import com.itextpdf.kernel.utils.PdfMerger import com.itextpdf.layout.Document -import hs.kr.entrydsm.application.global.document.pdf.data.PdfDataConverter -import hs.kr.entrydsm.application.global.document.pdf.data.TemplateFileName -import hs.kr.entrydsm.application.global.document.pdf.facade.PdfDocumentFacade +import hs.kr.entrydsm.application.global.pdf.data.PdfDataConverter +import hs.kr.entrydsm.application.global.pdf.data.TemplateFileName +import hs.kr.entrydsm.application.global.pdf.facade.PdfDocumentFacade import hs.kr.entrydsm.domain.application.aggregates.Application import hs.kr.entrydsm.domain.application.interfaces.ApplicationPdfGeneratorContract import hs.kr.entrydsm.domain.application.values.ApplicationType diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/IntroductionPdfGenerator.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/IntroductionPdfGenerator.kt similarity index 87% rename from casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/IntroductionPdfGenerator.kt rename to casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/IntroductionPdfGenerator.kt index f1f98054..65b6942c 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/IntroductionPdfGenerator.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/IntroductionPdfGenerator.kt @@ -1,16 +1,15 @@ -package hs.kr.entrydsm.application.global.document.pdf.generator +package hs.kr.entrydsm.application.global.pdf.generator import com.itextpdf.kernel.pdf.PdfDocument import com.itextpdf.kernel.pdf.PdfWriter import com.itextpdf.kernel.utils.PdfMerger -import hs.kr.entrydsm.application.global.document.pdf.data.IntroductionPdfConverter -import hs.kr.entrydsm.application.global.document.pdf.data.TemplateFileName -import hs.kr.entrydsm.application.global.document.pdf.facade.PdfDocumentFacade +import hs.kr.entrydsm.application.global.pdf.data.IntroductionPdfConverter +import hs.kr.entrydsm.application.global.pdf.data.TemplateFileName +import hs.kr.entrydsm.application.global.pdf.facade.PdfDocumentFacade import hs.kr.entrydsm.domain.application.aggregates.Application import hs.kr.entrydsm.domain.application.interfaces.IntroductionPdfGeneratorContract import org.springframework.stereotype.Component import java.io.ByteArrayOutputStream -import kotlin.collections.toMap /** * 소개서 PDF를 생성하는 Generator입니다. diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/PdfProcessor.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/PdfProcessor.kt similarity index 87% rename from casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/PdfProcessor.kt rename to casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/PdfProcessor.kt index bddd3562..b6e80dd0 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/PdfProcessor.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/PdfProcessor.kt @@ -1,7 +1,7 @@ -package hs.kr.entrydsm.application.global.document.pdf.generator +package hs.kr.entrydsm.application.global.pdf.generator import com.itextpdf.html2pdf.HtmlConverter -import hs.kr.entrydsm.application.global.document.pdf.config.ConverterPropertiesCreator +import hs.kr.entrydsm.application.global.pdf.config.ConverterPropertiesCreator import org.springframework.stereotype.Component import java.io.ByteArrayOutputStream diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/TemplateProcessor.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/TemplateProcessor.kt similarity index 93% rename from casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/TemplateProcessor.kt rename to casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/TemplateProcessor.kt index 2389500e..9c8c43f8 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/generator/TemplateProcessor.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/TemplateProcessor.kt @@ -1,4 +1,4 @@ -package hs.kr.entrydsm.application.global.document.pdf.generator +package hs.kr.entrydsm.application.global.pdf.generator import org.springframework.stereotype.Component import org.thymeleaf.TemplateEngine diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/presentation/PdfTestController.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/presentation/PdfTestController.kt similarity index 94% rename from casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/presentation/PdfTestController.kt rename to casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/presentation/PdfTestController.kt index 87710183..3cc14091 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/presentation/PdfTestController.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/presentation/PdfTestController.kt @@ -1,7 +1,7 @@ -package hs.kr.entrydsm.application.global.document.pdf.presentation +package hs.kr.entrydsm.application.global.pdf.presentation -import hs.kr.entrydsm.application.global.document.pdf.generator.ApplicationPdfGenerator -import hs.kr.entrydsm.application.global.document.pdf.generator.IntroductionPdfGenerator +import hs.kr.entrydsm.application.global.pdf.generator.ApplicationPdfGenerator +import hs.kr.entrydsm.application.global.pdf.generator.IntroductionPdfGenerator import hs.kr.entrydsm.domain.application.aggregates.Application import hs.kr.entrydsm.domain.application.values.ApplicationType import hs.kr.entrydsm.domain.status.values.ApplicationStatus From e451bf80f819286aacabab4a11e4fffd7073eca8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Sun, 21 Sep 2025 22:13:18 +0900 Subject: [PATCH 12/16] =?UTF-8?q?refactor=20(=20#51=20)=20:=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/pdf/data/PdfDataConverter.kt | 62 +++++++++++++------ 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/PdfDataConverter.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/PdfDataConverter.kt index 6b9f2e0a..5d7b1554 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/PdfDataConverter.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/PdfDataConverter.kt @@ -162,11 +162,32 @@ class PdfDataConverter( ) { values.putAll(emptyGraduationClassification()) - // TODO: 졸업정보 도메인이 없어서 더미값 사용 - val yearMonth = YearMonth.now() - values["graduateYear"] = yearMonth.year.toString() - values["graduateMonth"] = yearMonth.monthValue.toString() - values["educationalStatus"] = "${yearMonth.year}년 ${yearMonth.monthValue}월 중학교 졸업" + val currentYear = LocalDate.now().year + val graduationMonth = if (LocalDate.now().monthValue <= 2) 2 else 8 // 2월/8월 졸업 + + when (application.educationalStatus) { + "졸업" -> { + values["graduateYear"] = currentYear.toString() + values["graduateMonth"] = graduationMonth.toString() + values["educationalStatus"] = "${currentYear}년 ${graduationMonth}월 중학교 졸업" + } + "졸업예정" -> { + val graduateYear = currentYear + 1 + values["prospectiveGraduateYear"] = graduateYear.toString() + values["prospectiveGraduateMonth"] = "2" + values["educationalStatus"] = "${graduateYear}년 2월 중학교 졸업예정" + } + "검정고시" -> { + values["qualificationExamPassedYear"] = currentYear.toString() + values["qualificationExamPassedMonth"] = graduationMonth.toString() + values["educationalStatus"] = "${currentYear}년 ${graduationMonth}월 검정고시 합격" + } + else -> { + values["graduateYear"] = currentYear.toString() + values["graduateMonth"] = graduationMonth.toString() + values["educationalStatus"] = application.educationalStatus ?: "중학교 졸업" + } + } } private fun setUserType( @@ -175,26 +196,31 @@ class PdfDataConverter( ) { val isDaejeon = application.isDaejeon ?: false val isCommon = application.applicationType == ApplicationType.COMMON + val isSocial = application.applicationType == ApplicationType.SOCIAL + + val isQualificationExam = application.educationalStatus == "검정고시" + val isGraduate = application.educationalStatus == "졸업" + val isProspectiveGraduate = application.educationalStatus == "졸업예정" val list = listOf( - "isQualificationExam" to false, // TODO: 검정고시 정보 도메인 없어서 더미값 - "isGraduate" to true, // TODO: 졸업정보 도메인 없어서 더미값 - "isProspectiveGraduate" to false, // TODO: 졸업정보 도메인 없어서 더미값 + "isQualificationExam" to isQualificationExam, + "isGraduate" to isGraduate, + "isProspectiveGraduate" to isProspectiveGraduate, "isDaejeon" to isDaejeon, "isNotDaejeon" to !isDaejeon, - "isBasicLiving" to false, // TODO: 사회적배려 정보 도메인 없어서 더미값 - "isFromNorth" to false, // TODO: 사회적배려 정보 도메인 없어서 더미값 - "isLowestIncome" to false, // TODO: 사회적배려 정보 도메인 없어서 더미값 - "isMulticultural" to false, // TODO: 사회적배려 정보 도메인 없어서 더미값 - "isOneParent" to false, // TODO: 사회적배려 정보 도메인 없어서 더미값 - "isTeenHouseholder" to false, // TODO: 사회적배려 정보 도메인 없어서 더미값 - "isPrivilegedAdmission" to false, // TODO: 사회적배려 정보 도메인 없어서 더미값 - "isNationalMerit" to false, // TODO: 사회적배려 정보 도메인 없어서 더미값 - "isProtectedChildren" to false, // TODO: 사회적배려 정보 도메인 없어서 더미값 + "isBasicLiving" to isSocial, // 사회통합전형인 경우 사회적배려 대상자로 추정 + "isFromNorth" to false, // TODO: 사회적배려 세부 정보 도메인 없어서 더미값 + "isLowestIncome" to false, // TODO: 사회적배려 세부 정보 도메인 없어서 더미값 + "isMulticultural" to false, // TODO: 사회적배려 세부 정보 도메인 없어서 더미값 + "isOneParent" to false, // TODO: 사회적배려 세부 정보 도메인 없어서 더미값 + "isTeenHouseholder" to false, // TODO: 사회적배려 세부 정보 도메인 없어서 더미값 + "isPrivilegedAdmission" to false, // TODO: 사회적배려 세부 정보 도메인 없어서 더미값 + "isNationalMerit" to false, // TODO: 사회적배려 세부 정보 도메인 없어서 더미값 + "isProtectedChildren" to false, // TODO: 사회적배려 세부 정보 도메인 없어서 더미값 "isCommon" to isCommon, "isMeister" to (application.applicationType == ApplicationType.MEISTER), - "isSocialMerit" to (application.applicationType == ApplicationType.SOCIAL), + "isSocialMerit" to isSocial, ) list.forEach { (key, value) -> From 05e3274d0758937e3b3d66fa07b6549cc6f271c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Mon, 22 Sep 2025 16:13:27 +0900 Subject: [PATCH 13/16] =?UTF-8?q?refactor=20(=20#51=20)=20:=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=EB=84=A4=EC=9E=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/presentation/{ExcelController.kt => WebExcelAdapter.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/presentation/{ExcelController.kt => WebExcelAdapter.kt} (100%) diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/presentation/ExcelController.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/presentation/WebExcelAdapter.kt similarity index 100% rename from casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/presentation/ExcelController.kt rename to casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/excel/presentation/WebExcelAdapter.kt From fe169ecb88bf60726c70338de75b062df0362d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Mon, 22 Sep 2025 17:41:24 +0900 Subject: [PATCH 14/16] =?UTF-8?q?feat=20(=20#51=20)=20:=20=EB=AF=B8?= =?UTF-8?q?=EB=A6=AC=EB=B3=B4=EA=B8=B0=20request=EB=A1=9C=20=EB=B0=9B?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/WebApplicationPdfAdapter.kt | 12 ++- .../dto/request/PreviewPdfRequest.kt | 25 ++++++ .../GetPreviewApplicationPdfUseCase.kt | 77 ++++++++++++++----- .../global/document/pdf/PdfApiDocument.kt | 11 ++- 4 files changed, 101 insertions(+), 24 deletions(-) create mode 100644 casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/presentation/dto/request/PreviewPdfRequest.kt diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/presentation/WebApplicationPdfAdapter.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/presentation/WebApplicationPdfAdapter.kt index 763fc28a..167f1ea6 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/presentation/WebApplicationPdfAdapter.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/presentation/WebApplicationPdfAdapter.kt @@ -1,5 +1,6 @@ package hs.kr.entrydsm.application.domain.pdf.presentation +import hs.kr.entrydsm.application.domain.pdf.presentation.dto.request.PreviewPdfRequest import hs.kr.entrydsm.application.domain.pdf.usecase.GetFinalApplicationPdfUseCase import hs.kr.entrydsm.application.domain.pdf.usecase.GetPreviewApplicationPdfUseCase import hs.kr.entrydsm.application.global.document.pdf.PdfApiDocument @@ -7,6 +8,8 @@ import org.springframework.http.HttpHeaders import org.springframework.http.MediaType import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController import jakarta.servlet.http.HttpServletResponse @@ -18,9 +21,12 @@ class WebApplicationPdfAdapter( private val getPreviewApplicationPdfUseCase: GetPreviewApplicationPdfUseCase ) : PdfApiDocument { - @GetMapping("/preview") - override fun previewPdf(): ResponseEntity { - val pdfBytes = getPreviewApplicationPdfUseCase.execute() + /** + * 프론트에서 전달받은 임시저장 데이터로 미리보기 PDF 생성 + */ + @PostMapping("/preview") + override fun previewPdf(@RequestBody request: PreviewPdfRequest): ResponseEntity { + val pdfBytes = getPreviewApplicationPdfUseCase.execute(request.application, request.scores) return ResponseEntity.ok() .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PDF_VALUE) diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/presentation/dto/request/PreviewPdfRequest.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/presentation/dto/request/PreviewPdfRequest.kt new file mode 100644 index 00000000..a09ea0ac --- /dev/null +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/presentation/dto/request/PreviewPdfRequest.kt @@ -0,0 +1,25 @@ +package hs.kr.entrydsm.application.domain.pdf.presentation.dto.request + +/** + * PDF 미리보기 요청 DTO + * + * 프론트에서 IndexedDB에 저장된 임시 데이터를 전달받아 + * 미리보기 PDF를 생성하기 위한 요청 객체입니다. + */ +data class PreviewPdfRequest( + /** + * 원서 정보 + * + * 지원자의 개인정보, 전형유형, 학력상태, 학교정보, + * 자기소개서, 학업계획서 등이 포함됩니다. + */ + val application: Map, + + /** + * 성적 정보 + * + * 중학교 성적, 출석, 봉사활동 등의 정보가 + * Key-Value 형태로 포함됩니다. + */ + val scores: Map +) diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetPreviewApplicationPdfUseCase.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetPreviewApplicationPdfUseCase.kt index f4847543..b15205a5 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetPreviewApplicationPdfUseCase.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/pdf/usecase/GetPreviewApplicationPdfUseCase.kt @@ -1,36 +1,77 @@ package hs.kr.entrydsm.application.domain.pdf.usecase import hs.kr.entrydsm.application.global.annotation.usecase.ReadOnlyUseCase -import hs.kr.entrydsm.domain.application.interfaces.ApplicationContract +import hs.kr.entrydsm.domain.application.aggregates.Application import hs.kr.entrydsm.domain.application.interfaces.ApplicationPdfGeneratorContract -import hs.kr.entrydsm.domain.score.interfaces.ScoreContract +import hs.kr.entrydsm.domain.application.values.ApplicationType import hs.kr.entrydsm.domain.security.interfaces.SecurityContract -import hs.kr.entrydsm.domain.status.interfaces.ApplicationQueryStatusContract +import hs.kr.entrydsm.domain.status.values.ApplicationStatus +import java.time.LocalDateTime +import java.util.UUID @ReadOnlyUseCase class GetPreviewApplicationPdfUseCase( private val securityContract: SecurityContract, - private val applicationContract: ApplicationContract, - private val scoreContract: ScoreContract, - private val applicationPdfGeneratorContract: ApplicationPdfGeneratorContract, - private val applicationQueryStatusContract: ApplicationQueryStatusContract + private val applicationPdfGeneratorContract: ApplicationPdfGeneratorContract ) { - fun execute(): ByteArray { + /** + * 프론트에서 전달받은 임시저장 데이터로 미리보기 PDF 생성 + */ + fun execute(applicationData: Map, scoresData: Map): ByteArray { val userId = securityContract.getCurrentUserId() - val application = applicationContract.getApplicationByUserId(userId) - ?: throw IllegalStateException("원서 정보를 찾을 수 없습니다") - - validatePrintableApplication(application) - - // TODO: Score Contract 구현 후 실제 점수 조회 - val score = Any() // 임시 더미 객체 + // 프론트에서 전달받은 데이터로 실제 Application 도메인 객체 생성 + val tempApplication = createTempApplication(userId, applicationData) + + return applicationPdfGeneratorContract.generate(tempApplication, scoresData) + } - return applicationPdfGeneratorContract.generate(application, score) + /** + * 프론트에서 전달받은 데이터로 실제 Application 도메인 객체 생성 + */ + private fun createTempApplication(userId: UUID, data: Map): Application { + val now = LocalDateTime.now() + + return Application( + applicationId = UUID.randomUUID(), + userId = userId, + receiptCode = (data["receiptCode"] as? Number)?.toLong() ?: 0L, + applicantName = data["applicantName"]?.toString() ?: "", + applicantTel = data["applicantTel"]?.toString() ?: "", + parentName = data["parentName"]?.toString(), + parentTel = data["parentTel"]?.toString(), + birthDate = data["birthDate"]?.toString(), + applicationType = parseApplicationType(data["applicationType"]?.toString()), + educationalStatus = data["educationalStatus"]?.toString() ?: "", + status = ApplicationStatus.WRITING, // 미리보기는 작성 중 상태 + streetAddress = data["streetAddress"]?.toString(), + submittedAt = LocalDateTime.MIN, // 미제출 상태 표시 (임시값) + reviewedAt = null, + createdAt = now, + updatedAt = now, + isDaejeon = data["isDaejeon"] as? Boolean, + isOutOfHeadcount = data["isOutOfHeadcount"] as? Boolean ?: false, + photoPath = data["photoPath"]?.toString(), + parentRelation = data["parentRelation"]?.toString(), + postalCode = data["postalCode"]?.toString(), + detailAddress = data["detailAddress"]?.toString(), + studyPlan = data["studyPlan"]?.toString(), + selfIntroduce = data["selfIntroduce"]?.toString(), + veteransNumber = (data["veteransNumber"] as? Number)?.toInt(), + schoolCode = data["schoolCode"]?.toString() + ) } - private fun validatePrintableApplication(application: Any) { - // TODO: 교육 상태 검증 로직 구현 + /** + * 문자열을 ApplicationType enum으로 변환 + */ + private fun parseApplicationType(typeStr: String?): ApplicationType { + return when (typeStr?.uppercase()) { + "COMMON" -> ApplicationType.COMMON + "MEISTER" -> ApplicationType.MEISTER + "SOCIAL" -> ApplicationType.SOCIAL + else -> ApplicationType.COMMON // 기본값 + } } } diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/PdfApiDocument.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/PdfApiDocument.kt index 72eb0cc6..ee091d8b 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/PdfApiDocument.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/pdf/PdfApiDocument.kt @@ -1,5 +1,6 @@ package hs.kr.entrydsm.application.global.document.pdf +import hs.kr.entrydsm.application.domain.pdf.presentation.dto.request.PreviewPdfRequest import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.media.Content import io.swagger.v3.oas.annotations.media.Schema @@ -7,11 +8,15 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse import io.swagger.v3.oas.annotations.responses.ApiResponses import io.swagger.v3.oas.annotations.tags.Tag import org.springframework.http.ResponseEntity +import org.springframework.web.bind.annotation.RequestBody @Tag(name = "PDF API", description = "원서 PDF 관련 API") interface PdfApiDocument { - @Operation(summary = "원서 미리보기 PDF 조회", description = "작성 중인 원서의 미리보기 PDF를 조회합니다.") + @Operation( + summary = "원서 미리보기 PDF 조회", + description = "프론트에서 IndexedDB에 임시저장된 데이터를 받아 미리보기 PDF를 생성합니다." + ) @ApiResponses( value = [ ApiResponse( @@ -26,7 +31,7 @@ interface PdfApiDocument { ), ApiResponse( responseCode = "400", - description = "원서 정보를 찾을 수 없음", + description = "잘못된 요청 데이터", content = [Content()] ), ApiResponse( @@ -36,7 +41,7 @@ interface PdfApiDocument { ) ] ) - fun previewPdf(): ResponseEntity + fun previewPdf(@RequestBody request: PreviewPdfRequest): ResponseEntity @Operation(summary = "최종 원서 PDF 조회", description = "제출된 원서의 최종 PDF를 조회합니다.") @ApiResponses( From 4e0c260c1f09714bd032729cc59b410868adcce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Mon, 22 Sep 2025 17:41:44 +0900 Subject: [PATCH 15/16] =?UTF-8?q?refactor=20(=20#51=20)=20:=20admin=20pdf?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/admin/presentation/AdminController.kt | 10 +++++----- .../global/document/admin/AdminApiDocument.kt | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/admin/presentation/AdminController.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/admin/presentation/AdminController.kt index 1d437497..756a77f9 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/admin/presentation/AdminController.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/domain/admin/presentation/AdminController.kt @@ -26,18 +26,18 @@ class AdminController( private val adminUseCase: AdminUseCase, private val getIntroductionPdfUseCase: GetIntroductionPdfUseCase ) : AdminApiDocument { - + @GetMapping("/pdf/introduction", produces = [MediaType.APPLICATION_PDF_VALUE]) - override fun getIntroductionPdf(response: HttpServletResponse): ResponseEntity { + override suspend fun getIntroductionPdf(response: HttpServletResponse): ResponseEntity { val pdfBytes = getIntroductionPdfUseCase.execute() - + response.setHeader("Content-Disposition", "attachment; filename=\"${encodeFileName()}.pdf\"") - + return ResponseEntity.ok() .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_PDF_VALUE) .body(pdfBytes) } - + private fun encodeFileName(): String { val fileName = "introduction" return String(fileName.toByteArray(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1) diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/admin/AdminApiDocument.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/admin/AdminApiDocument.kt index 924bf5af..22839521 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/admin/AdminApiDocument.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/document/admin/AdminApiDocument.kt @@ -42,7 +42,7 @@ interface AdminApiDocument { ) ] ) - fun getIntroductionPdf(response: HttpServletResponse): ResponseEntity + suspend fun getIntroductionPdf(response: HttpServletResponse): ResponseEntity @Operation(summary = "전형 타입 생성", description = "새로운 전형 타입을 생성합니다.") @ApiResponses( From a5111864d51b62b753f590cc21f5dde6c600feaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=A3=BC=EC=9B=90?= Date: Mon, 29 Sep 2025 20:34:46 +0900 Subject: [PATCH 16/16] =?UTF-8?q?refactor=20(=20#51=20)=20:=20html=20?= =?UTF-8?q?=ED=98=95=EC=8B=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/pdf/data/TemplateFileName.kt | 3 + .../pdf/generator/ApplicationPdfGenerator.kt | 1 + .../templates/application_for_admission.html | 602 +++++++----------- .../templates/enrollment_agreement.html | 168 +++++ .../resources/templates/introduction.html | 115 ++-- .../main/resources/templates/nonsmoking.html | 380 ++++------- .../templates/privacy_agreement.html | 230 ++++--- .../resources/templates/recommendation.html | 210 +++--- .../resources/templates/smoking_examine.html | 376 ++++------- 9 files changed, 895 insertions(+), 1190 deletions(-) create mode 100644 casper-application-infrastructure/src/main/resources/templates/enrollment_agreement.html diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/TemplateFileName.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/TemplateFileName.kt index d79d6ec2..8d7a32a2 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/TemplateFileName.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/data/TemplateFileName.kt @@ -28,4 +28,7 @@ object TemplateFileName { /** 관리자용 소개서 템플릿 */ const val ADMIN_INTRODUCTION = "admin_introduction" + + /** 입학 동의서 템플릿 */ + const val ENROLLMENT_AGREEMENT = "enrollment_agreement" } diff --git a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/ApplicationPdfGenerator.kt b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/ApplicationPdfGenerator.kt index 27446c1e..fca135df 100644 --- a/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/ApplicationPdfGenerator.kt +++ b/casper-application-infrastructure/src/main/kotlin/hs/kr/entrydsm/application/global/pdf/generator/ApplicationPdfGenerator.kt @@ -93,6 +93,7 @@ class ApplicationPdfGenerator( TemplateFileName.INTRODUCTION, TemplateFileName.NON_SMOKING, TemplateFileName.SMOKING_EXAMINE, + TemplateFileName.ENROLLMENT_AGREEMENT, ), ) diff --git a/casper-application-infrastructure/src/main/resources/templates/application_for_admission.html b/casper-application-infrastructure/src/main/resources/templates/application_for_admission.html index 3a3d6efb..8fee2cb5 100644 --- a/casper-application-infrastructure/src/main/resources/templates/application_for_admission.html +++ b/casper-application-infrastructure/src/main/resources/templates/application_for_admission.html @@ -7,419 +7,265 @@ margin: 0; padding: 0; } + body { + font-family: KoPubWorld_Dotum_Light; + } td { border: 1px solid rgba(0,0,0,0.6); text-align: center; - font-size: small; + font-size: 11px; font-family: KoPubWorld_Dotum_Light; + padding: 4px; } th { background-color: #f2f2f2; text-align: center; border: 1px solid rgba(0,0,0,0.6); font-family: KoPubWorld_Dotum_Light; + font-size: 11px; + font-weight: 600; + padding: 4px; + } + .header-title { + text-align: center; + font-size: 16px; + font-weight: bold; + margin-bottom: 15px; + } + .section-title { + text-align: center; + font-size: 14px; + font-weight: bold; + margin-top: 20px; + margin-bottom: 15px; } -
-
- - 2024학년도 대덕소프트웨어마이스터고등학교 입학원서 - -
+
+ <서식 1> (인터넷접수 후 출력) +
+
+ + 2026학년도 대덕소프트웨어마이스터고등학교 입학원서 +
- + +
+ + + + + + + + - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
접수번호학교코드수험번호*기재하지 않음
- - - - - - - - - -
접수번호학교코드수험번호*기재하지 않음
+
지원자성명전화번호 + 사진(3cm×4cm) +
사진
(3cm×4cm)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
지원자성명전화번호 - # -
생년월일출신지역
성별출신학교
졸업구분
주소
- - - - - - - - - - -
보호자성명관계휴대전화
+
생년월일출신지역
성별출신학교
졸업구분
주소
보호자성명관계휴대전화
지역전형유형특기사항
+ + + + + + + + + + + + + + - + + + + + + - + + + + + + - + + + + + + - + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + +
교과성적(성취도)출결 및 봉사활동
교과3학년 2학기3학년 1학기직전학기직전전학기미인정결석 +
- - - - - - - - - -
지역전형유형특기사항
+
국어미인정지각 +
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- 교과성적(성취도) - - 출결 및 봉사활동 -
교과3학년 2학기3학년 1학기직전학기직전전학기미인정결석 - 일 -
국어미인정지각 - 회 -
사회미인정조퇴 - 회 -
역사미인정결과 - 회 -
수학봉사활동 시간 - 시간 -
과학가산점
DSM알고리즘대회
영어정보처리기능사
+
사회미인정조퇴 +
- - - - - -
-

- 본인은 귀 고등학교에 입학하고자 소정의 서류를 갖추어 - 지원합니다. -

-

- 월 - 일 -

-
-
- 지원자: - - - - - (서명 또는 인) - -
-
- 보호자: - - - - - (서명 또는 인) - -
-
-

- 대덕소프트웨어마이스터고등학교장 귀하 -

-
-

- 보훈번호 : () -

-

- 위 학생은 국가유공자자녀임을 확인함. -

-

- 월 - 일 -

- 교사: - - (서명 또는 인) -
+
역사미인정결과 +
- - -
-

- 추 천 서 -

-

- 본 입학원서의 내용은 사실과 다름이 없으며, 위 학생은 귀교에 입학 - 적격자로 인정되므로 추천합니다. -

-

- 월 - 일 -

-

- 장 (직인) -

-

- 대덕소프트웨어마이스터고등학교장 귀하 -

-
+
수학봉사활동 시간 + 시간
- - - - - - - -
원서작성자 - 교사: - - (서명 또는 인) - 연락처
+
과학가산점
기술∙가정DSM알고리즘대회
영어정보처리기능사
+ +
+
+ 본인은 귀 고등학교에 입학하고자 소정의 서류를 갖추어 지원합니다. +
+
+ 2025년 + 월 + 일 +
+ + + + + +
+
+
지원자 : (서명 또는 인)
+
보호자 : (서명 또는 인)
+
+
대덕소프트웨어마이스터고등학교장 귀하
+
+
보훈번호:()
+
위 학생은 국가유공자자녀임을 확인함.
+
+ 2025년 + 월 + 일 +
+
+ 교사: (서명 또는 인) +
+
+
+ +
추 천 서
+
+
+ 본 입학원서의 내용은 사실과 다름이 없으며, 위 학생은 귀교에 입학 적격자로 인정되므로 추천합니다. +
+
+ 2025년 + 월 + 일 +
+
+ 장 (직인) +
+
+ 대덕소프트웨어마이스터고등학교장 귀하 +
+
+ + + + + + +
원서작성자 + 교사: (서명 또는 인) 연락처
+ +
- 13 -
- + \ No newline at end of file diff --git a/casper-application-infrastructure/src/main/resources/templates/enrollment_agreement.html b/casper-application-infrastructure/src/main/resources/templates/enrollment_agreement.html new file mode 100644 index 00000000..4ea26b63 --- /dev/null +++ b/casper-application-infrastructure/src/main/resources/templates/enrollment_agreement.html @@ -0,0 +1,168 @@ + + + + + + + +
+
<서식 7> 최종 합격자 제출 서류
+
+
+ 입학 동의서 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
2026학년도 신입생 입학전형수험번호
지원자성 명성 별□남    □여
전화번호생년월일 + 년 + 월 + 일 +
주 소
보호자성 명지원자와의 관계지원자의 ()
전화번호
+ +
+
+

+ 위 지원자는 2026학년도 대덕소프트웨어마이스터고등학교 신입생 입학전형에 합격하여, + 본교 입학생으로서의 긍지와 자부심을 가지고 성실히 학교생활에 임하고 학교규칙을 준수할 + 것을 서약하며, 보호자 연서로 입학동의서를 제출합니다. +

+
+ +
+

□ 개인정보 수집·이용 동의

+ + + + + + + + + + + +
항 목수집목적보유기간
학생(성명, 성별, 생년월일, 주소, 연락처)
학부모(성명, 연락처)
입학동의1년
+ + + + + + +
개인정보 수집·이용 동의□예      □아니요
+ +
+ 2025년 + 월 + 일 +
+ + + + + + + + + + + + +
지원자 성명 :(서명 또는 인)
보호자 성명 :(서명 또는 인)
+ +
+ 대덕소프트웨어마이스터고등학교장 귀하 +
+ +
+ ※ 제출 방법 +
+
+

+ - 입학 동의서 작성 후 서명하여 인편 또는 등기우편으로 2025. 11. 14.(금) 17:00까지 제출 +

+

+ 직접 제출 시 : 대덕소프트웨어마이스터고 등록 접수처 +

+

+ 우편 제출 시 : (우) 34111 대전광역시 유성구 가정북로 76(장동 23-9)
+ 대덕소프트웨어마이스터고 SW교육부 +

+
+ +
+

※ 개인정보 수집·이용에 대한 동의를 거부할 권리가 있습니다. 그러나 동의를 거부할 경우

+

최종 입학에 제한을 받을 수 있습니다.

+
+
+
+ +
- 19 -
+ + \ No newline at end of file diff --git a/casper-application-infrastructure/src/main/resources/templates/introduction.html b/casper-application-infrastructure/src/main/resources/templates/introduction.html index ea165934..6a1dd964 100644 --- a/casper-application-infrastructure/src/main/resources/templates/introduction.html +++ b/casper-application-infrastructure/src/main/resources/templates/introduction.html @@ -3,78 +3,113 @@ - application.html + 자기소개서 및 학업계획서 - -
-

- - 자기소개서 및 학업계획서 - -

+ +
+
<서식 3> (인터넷접수 후 출력)
- +
+ 자기소개서 및 학업계획서 +
+ +
- - - - - + + + + - - - - + + + + - - + +
인적
사항
성명 - - (서명 또는 인) - - 접 수 번 호 - + 인적
사항
성 명 + (서명) 접수번호
연락처출신 중학교전화번호출신학교
주소주 소
- + +
- - +
자기소개서 내용은 특별한 형식이 없으며 개인의 특성 및 성장 과정, 취미·특기, 학교 생활, 가족 - 안에서의 역할, 남들보다 뛰어나다고 생각하는 자신의 장점(특성 혹은 능력)과 보완·발전시켜야 할 단점에 대하여 기술하십시오. + + ◎ 자기소개서 내용은 특별한 형식이 없으며 개인의 특성 및 성장 과정, 취미 · 특기, 학교 생활, 가 + 족 안에서의 역할, 남들보다 뛰어나다고 생각하는 자신의 장점(특성 혹은 능력)과 보완 · 발전시켜야 + 할 단점에 대하여 기술하십시오. +
(빈칸 포함 1,600자 이내)
-

+

+
- + +
- - +
학업계획서는 자신이 본교를 선택하게 된 구체적인 사유(지원 동기)와 고등학생이 된 후 이루고자 하는
목표를 - 달성하기 위한 학업계획을 상세하게 기술하십시오. +
+ ◎ 학업계획서는 자신이 본교를 선택하게 된 구체적인 사유(지원 동기)와 고등학생이 된 후 이루고자 + 하는 목표를 달성하기 위한 학업계획을 상세하게 기술하십시오. +
(빈칸 포함 1,600자 이내)
-

+

+
-
+ +
- 15 -
\ No newline at end of file diff --git a/casper-application-infrastructure/src/main/resources/templates/nonsmoking.html b/casper-application-infrastructure/src/main/resources/templates/nonsmoking.html index bc295fc0..81c4f38d 100644 --- a/casper-application-infrastructure/src/main/resources/templates/nonsmoking.html +++ b/casper-application-infrastructure/src/main/resources/templates/nonsmoking.html @@ -3,303 +3,137 @@ -
금 연 동 의 서
-
- +
+
<서식 5> (인터넷접수 후 출력)
+
+
+ 금연 동의서 +
+ +
- - - - - + + + + + - - - - + + + + - - - - - + +
인적
사항
성명접 수 번 호인적
사항
성 명접수번호
연락처출신 중학교전화번호출신학교
주소
-
-
-
-

하나, 나 자신의 건강을 위해서 흡연하지 않겠습니다.

-

하나, 흡연의 유혹에 절대로 흔들리지 않겠습니다.

-

- 하나, 흡연하는 친구가 있으면 충고하여 금연할 수 있도록 - 돕겠습니다. -

-
-

- 나 ()은(는) 장차 소프트웨어 분야를 선도할 전문가로 성장하기 위하여 - 흡연하지 않겠습니다. -

-

- 보호자는 지원자가 금연하는 데 용기와 도움을 줄 것을 약속합니다. -

-
-
-

□ 개인정보 수집·이용 동의

- - - - - - - - - - - -
항 목수집목적보유기간
-

학생(성명, 연락처,

-

출신 중학교, 주소)

-
금연동의서3년
-
-

- ※ 개인정보 수집·이용에 대한 동의를 거부할 권리가 있습니다. -

-

-   그러나 동의를 거부할 경우 최종 입학에 제한을 받을 수 - 있습니다 -

-
- - - - - -
개인정보 수집·이용 동의 - □ 예 -                - □ 아니요 -
-
-
-
-

- - 2024년        월 -        일 -

-
- - - - - - - - - - - -
지원자 성명(서명 또는 인)
보호자 성명(서명 또는 인)
-
주 소
+ +
+
+

하나, 나 자신의 건강을 위해서 흡연하지 않겠습니다.

+

하나, 흡연의 유혹에 절대로 흔들리지 않겠습니다.

+

하나, 흡연하는 친구가 있으면 충고하여 금연할 수 있도록 돕겠습니다.

+
+ +
+

+ 나 ()은(는) 장차 소프트웨어 분야를 선도할 전문가로 성장하기 위하여 흡연하지 않겠습니다. +

+

보호자는 지원자가 금연하는 데 용기와 도움을 줄 것을 약속합니다.

+
+ +
+

□ 개인정보 수집·이용 동의

+ + + + + + + + + + + +
항 목수집목적보유기간
학생(성명, 연락처,
출신 중학교, 주소)
금연 동의3년
+ +
+

※ 개인정보 수집·이용에 대한 동의를 거부할 권리가 있습니다. 그러나 동의를 거부할 경우

+

최종 입학에 제한을 받을 수 있습니다.

+
+ + + + + + +
개인정보 수집·이용 동의□예      □아니요
+ +
+ 2025년 + 월 + 일 +
+ + + + + + + + + + + + +
지원자 성명:(서명 또는 인)
보호자 성명:(서명 또는 인)
+
+
+ +
- 17 -
\ No newline at end of file diff --git a/casper-application-infrastructure/src/main/resources/templates/privacy_agreement.html b/casper-application-infrastructure/src/main/resources/templates/privacy_agreement.html index ab02bba8..bf87b1ae 100644 --- a/casper-application-infrastructure/src/main/resources/templates/privacy_agreement.html +++ b/casper-application-infrastructure/src/main/resources/templates/privacy_agreement.html @@ -1,134 +1,130 @@ - + - Document + 개인정보 수집 및 이용 동의서 -

개인정보 수집 및 이용 동의서

-
-
-    본 입학원서에 기재된 지원자의 개인정보는 신입생 - 입학관리업무의 원활한 수행을 위하여 개인정보의 - 수집.유출.오용.남용으로부터 사생활의 비밀 등을 보호하도록 한 - 개인정보보호법 규정에 따라 다음과 같이 수집.이용.제공됩니다. - ​ -

-
- 1. (개인정보 처리의 법령상 근거) 본 입학원서에 기재된 개인정보의 - 처리업무는 초.중등교육법 제47조 및 동법 시행령 제81조, 제82조, 제84조, - 제98조 및 본교의 입학전형 실시계획 등에 근거하고 있습니다.

- 2. (정보주체의 권리) 지원자는 자신이 제공한 개인정보에 대하여 개인정보 - 보호법 제4조 및 제35조부터 제38조까지에 따라 - 열람.처리.정지.정정.삭제.파기 등을 요구할 수 있으며, 개인정보 보호법을 - 위반한 행위로 인한 손해 발생 시에는 개인정보 보호법 제39조에 따라 - 손해배상을 청구할 수 있습니다.

- 3. (개인정보 수집항목) 입학관리 업무의 원활한 수행을 위하여 - 수집하는 개인정보는 성명, 생년월일, 증명사진, 주소, 전화번호, 학력, - 출결사항, 교과성적 - 등입니다.

- 4. (개인정보의 수집.이용 목적) 수집한 지원자의 개인정보는 - 원서접수, 지원자격.지원결격 사유 확인, 지원자 본인확인, 성적산출, - 합격자 명부 관리, 합격증명서 발급, 성적 통지, 통계자료 산출 - 등 입학관리 업무를 위한 정보로 이용됩니다.

- 5. (개인정보 제공) 수집한 개인정보는 지원자격.지원결격 사유 조회 및 - 교과성적 확인 등을 위하여 지원자가 졸업한 중학교 등 관련된 기관에 - 제공될 수 있습니다.

- 6. (개인정보의 보유기간 및 이용기간) 수집한 개인정보는 - 입학관리 업무를 계속하는 동안 보유.이용할 수 있으며, - 입학관리 업무 완료 후 5년간 보관의 목적으로만 관리하고 이후 - 에는 바로 폐기합니다.

- 7. (개인정보의 수집.이용.제공에 대한 동의 거부) 지원자는 개인정보의 - 수집.이용.제공에 대한 동의를 거부할 수 있으며, 동의를 거부할 경우 - 지원결격 사유 조회 등 입학관리 업무를 수행할 수 없으므로 원서를 접수할 - 수 없습니다. -
+
+
<서식 2> (인터넷접수 후 출력)
+
+
+ 개인정보 수집 및 이용 동의서 +
+ +
+
+ 본 입학원서에 기재된 지원자의 개인정보는 신입생 입학관리업무의 원활한 수행을 위하여 + 개인정보의 수집∙유출∙오용∙남용으로부터 사생활의 비밀 등을 보호하도록 한 개인정보보호법 + 규정에 따라 다음과 같이 수집∙이용∙제공됩니다. +
+ +
+ 1. (개인정보 처리의 법령상 근거) 본 입학원서에 기재된 개인정보의 처리업무는 초∙중등교육법 + 제47조 및 동법 시행령 제81조, 제82조, 제84조, 제98조 및 본교의 입학전형 실시계획 + 등에 근거하고 있습니다. +
+ +
+ 2. (정보주체의 권리) 지원자는 자신이 제공한 개인정보에 대하여 개인정보 보호법 제4조 및 + 제35조부터 제38조까지에 따라 열람∙처리∙정지∙정정∙삭제∙파기 등을 요구할 수 있으며, 개인정보 + 보호법을 위반한 행위로 인한 손해 발생 시에는 개인정보 보호법 제39조에 따라 손해배상을 + 청구할 수 있습니다. +
+ +
+ 3. (개인정보 수집항목) 입학관리 업무의 원활한 수행을 위하여 수집하는 개인정보는 성명, + 생년월일, 증명사진, 주소, 전화번호, 학력, 출결사항, 교과성적, 봉사활동사항 등입니다. +
+ +
+ 4. (개인정보의 수집∙이용 목적) 수집한 지원자의 개인정보는 원서접수, 지원자격∙지원결격 + 사유 확인, 지원자 본인확인, 성적산출, 합격자 명부 관리, 합격증명서 발급, 성적 통지, + 통계자료 산출 등 입학관리 업무를 위한 정보로 이용됩니다. +
+ +
+ 5. (개인정보 제공) 수집한 개인정보는 지원자격∙지원결격 사유 조회 및 교과성적 확인 등을 + 위하여 지원자가 졸업한 중학교 등 관련된 기관에 제공될 수 있습니다. +
+ +
+ 6. (개인정보의 보유기간 및 이용기간) 수집한 개인정보는 입학관리 업무를 계속하는 동안 + 보유∙이용할 수 있으며, 입학관리 업무 완료 후 5년간 보관의 목적으로만 관리하고 이후 + 에는 바로 폐기합니다. +
+ +
+ 7. (개인정보의 수집∙이용∙제공에 대한 동의 거부) 지원자는 개인정보의 수집∙이용∙제공에 대한 + 동의를 거부할 수 있으며, 동의를 거부할 경우 지원결격 사유 조회 등 입학관리 업무를 + 수행할 수 없으므로 원서를 접수할 수 없습니다.
-
-
- - - - + +
+
- 개인정보 수집·이용 - 동의                                                                 - - □ 예 -                - □ 아니요 -
+ + +
개인정보 수집 · 이용 동의□예      □아니요
-
-
- 2024년 -         월 -         일 + +
+
+ 2025년 + 월 + 일 +
+ + + + + +
+
지원자 성명: (서명 또는 인)
+
보호자 성명: (서명 또는 인)
+
+ +
+ 대덕소프트웨어마이스터고등학교장 귀하 +
- - - - - - - - - - - -
지원자 성명김정현(서명 또는 인)
보호자 성명(서명 또는 인)
-
-대덕소프트웨어마이스터고등학교장 귀하 + +
- 14 -
\ No newline at end of file diff --git a/casper-application-infrastructure/src/main/resources/templates/recommendation.html b/casper-application-infrastructure/src/main/resources/templates/recommendation.html index 2405e1e3..b9a7f4fe 100644 --- a/casper-application-infrastructure/src/main/resources/templates/recommendation.html +++ b/casper-application-infrastructure/src/main/resources/templates/recommendation.html @@ -3,135 +3,105 @@ - Document + 학교장 추천서 - -

학 교 장 추 천 서

- - - - - -
접수번호 :
-


-
-
-
-
-

-
-
-
- 3학년 -
- 반 -
-
-
-
- 성명: -


-
-
-
-

- 특별전형 추천 분야 -

- - - - - - - - - - - - - - - - - - -
- 구분 - - 마이스터 인재 전형 - - 사회통합 전형 -
대전
전국
-
-

- 위 학생을 2021학년도 대덕소프트웨어마이스터고등학교 특별전형 -

-

대상자로 추천합니다.

-
-
- 2020년        월        일 -
-
-

작성자 담임: -

- (서명 또는 인)

+ +
+
<서식 4> (인터넷접수 후 출력)
+
+
+ 학교장 추천서 +
+ +
+ 접수번호: +
+ +
+
+
+ ()중학교
-
- - (직인) +
+ 3학년 ()반
-
-

대덕소프트웨어마이스터고등학교장 귀하

+
+ 성 명 :
+ +
+ 특별전형 추천분야 +
+ + + + + + + + + + + + + + + + + +
구분마이스터 인재 전형사회통합 전형
대전
전국
+ +
+

위 학생을 2026학년도 대덕소프트웨어마이스터고등학교 특별전형

+

대상자로 추천합니다.

+
+ +
+ 2025년 + 월 + 일 +
+ +
+ 작성자 담임교사 : (서명 또는 인) +
+ +
+ [ ] 중학교장 (직인) +
+ +
+ 대덕소프트웨어마이스터고등학교장 귀하 +
+ +
- 16 -
\ No newline at end of file diff --git a/casper-application-infrastructure/src/main/resources/templates/smoking_examine.html b/casper-application-infrastructure/src/main/resources/templates/smoking_examine.html index 4cc60d6f..aa48eb93 100644 --- a/casper-application-infrastructure/src/main/resources/templates/smoking_examine.html +++ b/casper-application-infrastructure/src/main/resources/templates/smoking_examine.html @@ -3,289 +3,141 @@ -
흡 연 검 사 동 의 서
-
- - - - - - - - - - - - - +
+
<서식 6> (인터넷접수 후 출력)
+
+
+ 흡연 검사 동의서 +
+ +
인적
사항
성명접 수 번 호
연락처출신 중학교
+ + + + + + - - - + + + + + - - + + +
인적
사항
성 명접수번호
주소
전화번호출신학교
-
-

-   대덕소프트웨어마이스터고등학교에서는 안전한 기숙사 생활과 - 학생들의 건강을 위해 신입생 입학 전형자를 대상으로 소변 니코틴 - 검사 측정을 합니다. 이에 흡연검사에 - 학생과 보호자의 동의를 구합니다.
-   검사 시 약간의 불편이 있더라도 흡연자 지도를 위해서는 - 필요한 사안이므로 양해와 적극적인 협조를 부탁드립니다. -
-   학생들의 건강을 위해 흡연을 규제하고 예방하도록 학생 지도에 - 최선을 다하겠습니다. 학부모님께서도 귀 자녀가 흡연의 위험성을 - 인지하고 흡연하지 않도록 지도와 협조를 부탁드립니다. -

-
-
-
-
-
-

□ 개인정보 수집 · 이용 동의

- - - - - - - - - - - -
항 목수집목적보유기간
-

학생(성명, 연락처,

-

출신 중학교, 주소)

-
흡연검사동의3년
-
-

- ※ 개인정보 수집 · 이용에 대한 동의를 거부할 권리가 있습니다.그러나 - 동의를 거부할 경우 최종 입학에 제한을 받을 수 있습니다. -

-
- - - - - -
-     개인정보 수집 · 이용 동의 - - □ 예 -                - □ 아니요 -
-
-
-
-

- - 2024년        월 -        일 -

-
- - - - - - - - - - - -
지원자 성명:(서명 또는 인)
보호자 성명:(서명 또는 인)
-
주 소
+ +
+
+

+ 대덕소프트웨어마이스터고등학교에서는 안전한 기숙사 생활과 학생들의 + 건강을 위해 신입생 입학 전형자를 대상으로 소변 니코틴 검사 측정을 합니다. + 이에 흡연검사에 학생과 보호자의 동의를 구합니다. +

+

+ 검사 시 약간의 불편이 있더라도 흡연자 지도를 위해서는 필요한 사안 + 이므로 양해와 적극적인 협조를 부탁드립니다. +

+

+ 학생들의 건강을 위해 흡연을 규제하고 예방하도록 학생 지도에 최선을 다 + 하겠습니다. 학부모님께서도 귀 자녀가 흡연의 위험성을 인지하고 흡연하지 + 않도록 지도와 협조를 부탁드립니다. +

+
+ +
+

□ 개인정보 수집·이용 동의

+ + + + + + + + + + + +
항 목수집목적보유기간
학생(성명, 연락처,
출신 중학교, 주소)
흡연검사 동의3년
+ + + + + + +
개인정보 수집·이용 동의□예      □아니요
+ +
+ 2025년 + 월 + 일 +
+ + + + + + + + + + + + +
지원자 성명:(서명 또는 인)
보호자 성명:(서명 또는 인)
+ +
+

※ 개인정보 수집·이용에 대한 동의를 거부할 권리가 있습니다. 그러나 동의를 거부할 경우

+

최종 입학에 제한을 받을 수 있습니다.

+
+
+
+ +
- 18 -
\ No newline at end of file