Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cert/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,6 @@ Thumbs.db
# Temporary files
*.tmp
*.temp

backend/scripts
backend/src/assets/templates/*.png
11 changes: 11 additions & 0 deletions cert/backend/config/default_periods.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"3": { "start": "2021-07-16", "end": "2021-10-08" },
"4": { "start": "2022-03-07", "end": "2022-05-29" },
"5": { "start": "2022-09-05", "end": "2022-11-27" },
"6": { "start": "2023-03-15", "end": "2023-06-07" },
"7": { "start": "2023-08-21", "end": "2023-11-12" },
"8": { "start": "2024-03-03", "end": "2024-05-26" },
"9": { "start": "2024-08-04", "end": "2024-10-27" },
"10": { "start": "2025-03-02", "end": "2025-05-25" },
"11": { "start": "2025-09-08", "end": "2025-11-30" }
}
Binary file not shown.
Binary file not shown.
1 change: 1 addition & 0 deletions cert/backend/src/models/certificate.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class CertificateStatus(str, Enum):
"""์ˆ˜๋ฃŒ์ฆ ์ƒํƒœ"""
PENDING = "Pending"
NOT_ELIGIBLE = "Not Eligible"
REISSUED = "Reissued"
ISSUED = "Issued"
SYSTEM_ERROR = "System Error"

Expand Down
49 changes: 43 additions & 6 deletions cert/backend/src/services/certificate_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,30 @@ async def create_certificate(certificate_data: dict) -> CertificateResponse:

# ๊ธฐ์กด ์ˆ˜๋ฃŒ์ฆ ํ™•์ธ์ด ์„ฑ๊ณตํ•˜๊ณ  ๊ธฐ์กด ์ˆ˜๋ฃŒ์ฆ์ด ์žˆ๋Š” ๊ฒฝ์šฐ ์žฌ๋ฐœ๊ธ‰ ์ฒ˜๋ฆฌ
if existing_cert and existing_cert.get("found"):
existing_status = existing_cert.get("status", "")
if existing_status in [CertificateStatus.ISSUED, CertificateStatus.REISSUED]:
logger.info(
"๊ธฐ์กด ์ˆ˜๋ฃŒ์ฆ ๋ฐœ๊ฒฌ (์žฌ๋ฐœ๊ธ‰ ์ง„ํ–‰)",
extra={
"certificate_number": existing_cert.get("certificate_number"),
"applicant_name": certificate_data.get("applicant_name"),
"season": certificate_data.get("season"),
"status": existing_status,
},
)
return await CertificateService._reissue_certificate(
certificate_data, existing_cert, notion_client
)

logger.info(
"๊ธฐ์กด ์ˆ˜๋ฃŒ์ฆ ๋ฐœ๊ฒฌ",
"๊ธฐ์กด ์ˆ˜๋ฃŒ์ฆ ๋ฐœ๊ฒฌํ–ˆ์ง€๋งŒ ์ƒํƒœ๊ฐ€ Issued/Reissued๊ฐ€ ์•„๋‹˜. ์‹ ๊ทœ ๋ฐœ๊ธ‰์œผ๋กœ ์ง„ํ–‰",
extra={
"certificate_number": existing_cert.get("certificate_number"),
"applicant_name": certificate_data.get("applicant_name"),
"season": certificate_data.get("season"),
"status": existing_status,
},
)
return await CertificateService._reissue_certificate(
certificate_data, existing_cert, notion_client
)

# 2. ์‹ ๊ทœ ์ˆ˜๋ฃŒ์ฆ ๋ฐœ๊ธ‰ ์ฒ˜๋ฆฌ
return await CertificateService._create_new_certificate(
Expand Down Expand Up @@ -140,6 +153,9 @@ async def _reissue_certificate(
extra={"certificate_number": existing_cert_number},
)

# ๋ฐœ๊ธ‰์ผ(์žฌ๋ฐœ๊ธ‰ ์‹œ์  ๊ธฐ์ค€)
issue_date = datetime.now().strftime("%Y-%m-%d")

# PDF ์ˆ˜๋ฃŒ์ฆ ์žฌ์ƒ์„ฑ
pdf_generator = PDFGenerator()
pdf_bytes = pdf_generator.create_certificate(
Expand All @@ -148,6 +164,8 @@ async def _reissue_certificate(
course_name=certificate_data["course_name"],
role=participation_info["user_role"],
period=participation_info["period"],
certificate_number=existing_cert_number,
issue_date=issue_date,
)

# ์ด๋ฉ”์ผ ์žฌ๋ฐœ์†ก
Expand All @@ -160,6 +178,22 @@ async def _reissue_certificate(
role=participation_info["user_role"],
certificate_bytes=pdf_bytes
)

# ์žฌ๋ฐœ๊ธ‰ ๋กœ๊ทธ ๊ธฐ๋ก
reissue_log = await notion_client.log_certificate_reissue(
certificate_data=certificate_data,
certificate_number=existing_cert_number,
role=participation_info["user_role"],
issue_date=issue_date
)
if not reissue_log:
logger.warning(
"์žฌ๋ฐœ๊ธ‰ ๋กœ๊ทธ ๊ธฐ๋ก ์‹คํŒจ",
extra={
"certificate_number": existing_cert_number,
"recipient_email": certificate_data["recipient_email"],
},
)

# ๊ธฐ์กด ์ˆ˜๋ฃŒ์ฆ ์ƒํƒœ๋ฅผ ์žฌ๋ฐœ๊ธ‰์œผ๋กœ ์—…๋ฐ์ดํŠธ
await notion_client.update_certificate_status(
Expand All @@ -185,7 +219,7 @@ async def _reissue_certificate(
name=certificate_data["applicant_name"],
recipient_email=certificate_data["recipient_email"],
certificate_number=existing_cert_number,
issue_date=datetime.now().strftime("%Y-%m-%d"),
issue_date=issue_date,
certificate_status=CertificateStatus.ISSUED,
season=certificate_data["season"],
course_name=certificate_data["course_name"],
Expand Down Expand Up @@ -226,6 +260,7 @@ async def _create_new_certificate(

# TODO: ์ž„์‹œ ๊ฐ’, ์ถ”ํ›„ ์ˆ˜์ • ํ•„์š”
certificate_number = f"CERT-{datetime.now().year}{participation_info['project_code']}{str(uuid.uuid4())[:2].upper()}"
issue_date = datetime.now().strftime("%Y-%m-%d")

# PDF ์ˆ˜๋ฃŒ์ฆ ์ƒ์„ฑ
pdf_generator = PDFGenerator()
Expand All @@ -235,6 +270,8 @@ async def _create_new_certificate(
course_name=certificate_data["course_name"],
role=participation_info["user_role"],
period=participation_info["period"],
certificate_number=certificate_number,
issue_date=issue_date,
)
# ์ด๋ฉ”์ผ ๋ฐœ์†ก
email_sender = EmailSender()
Expand Down Expand Up @@ -281,7 +318,7 @@ async def _create_new_certificate(
name=certificate_data["applicant_name"],
recipient_email=certificate_data["recipient_email"],
certificate_number=certificate_number,
issue_date=datetime.now().strftime("%Y-%m-%d"),
issue_date=issue_date,
certificate_status=CertificateStatus.ISSUED,
season=certificate_data["season"],
course_name=certificate_data["course_name"],
Expand Down
Loading
Loading