Skip to content

Commit 580d807

Browse files
orabeCopilot
andcommitted
Add course_link field to certificate model and implement delete functionality
Co-authored-by: Copilot <copilot@github.com>
1 parent 55614bb commit 580d807

7 files changed

Lines changed: 97 additions & 1 deletion

File tree

backend/app/crud.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def create_certificate(db: Session, cert_in: schemas.CertificateCreate):
2929
course_level=cert_in.course_level,
3030
course_format=cert_in.course_format,
3131
instruction_language=cert_in.instruction_language,
32+
course_link=cert_in.course_link,
3233
issuer=cert_in.issuer or "MathCodeLab",
3334
instructor=cert_in.instructor or "Mohammad Orabe",
3435
)
@@ -44,3 +45,13 @@ def revoke_certificate(db: Session, certificate_id: str, reason: str = None):
4445
return None
4546
# Revocation removed: function retained only for compatibility but does nothing
4647
return None
48+
49+
50+
def delete_certificate(db: Session, certificate_id: str):
51+
cert = get_certificate_by_public_id(db, certificate_id)
52+
if not cert:
53+
return None
54+
55+
db.delete(cert)
56+
db.commit()
57+
return cert

backend/app/database.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ def ensure_certificate_schema(bind=None):
5353
missing_statements.append("ALTER TABLE certificates ADD COLUMN course_format VARCHAR")
5454
if "instruction_language" not in existing_columns:
5555
missing_statements.append("ALTER TABLE certificates ADD COLUMN instruction_language VARCHAR")
56+
if "course_link" not in existing_columns:
57+
missing_statements.append("ALTER TABLE certificates ADD COLUMN course_link VARCHAR")
5658

5759
if not missing_statements:
5860
return

backend/app/main.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ def verify_certificate(certificate_id: str, db: Session = Depends(get_db)):
7070
"certificate_id": cert.certificate_id,
7171
"student_name": cert.student_name,
7272
"course_title": cert.course_title,
73+
"course_link": cert.course_link,
7374
"completion_date": cert.completion_date,
7475
"duration_hours": cert.duration_hours,
7576
"issuer": cert.issuer,
@@ -94,4 +95,20 @@ def list_certificates(
9495
api_key: str = Depends(security.verify_api_key)
9596
):
9697
certs = db.query(models.Certificate).all()
97-
return certs
98+
return certs
99+
100+
101+
@app.delete("/admin/certificates/{certificate_id}", response_model=schemas.CertificateDeleteResponse)
102+
def delete_certificate(
103+
certificate_id: str,
104+
db: Session = Depends(get_db),
105+
api_key: str = Depends(security.verify_api_key)
106+
):
107+
cert = crud.delete_certificate(db, certificate_id)
108+
if not cert:
109+
raise HTTPException(status_code=404, detail="Certificate not found")
110+
111+
return {
112+
"message": "Certificate deleted",
113+
"certificate_id": certificate_id,
114+
}

backend/app/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class Certificate(Base):
1515
course_level = Column(String, nullable=True)
1616
course_format = Column(String, nullable=True)
1717
instruction_language = Column(String, nullable=True)
18+
course_link = Column(String, nullable=True)
1819

1920
issuer = Column(String, default="MathCodeLab", nullable=False)
2021
instructor = Column(String, default="Mohammad Orabe", nullable=False)

backend/app/schemas.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class CertificateBase(BaseModel):
1111
course_level: Optional[str] = None
1212
course_format: Optional[str] = None
1313
instruction_language: Optional[str] = None
14+
course_link: Optional[str] = None
1415
issuer: Optional[str] = "MathCodeLab"
1516
instructor: Optional[str] = "Mohammad Orabe"
1617

@@ -21,13 +22,15 @@ class CertificateOut(CertificateBase):
2122
certificate_id: str
2223
class Config:
2324
from_attributes = True
25+
course_link: Optional[str] = None
2426

2527
class CertificateVerificationResponse(BaseModel):
2628
status: str
2729
certificate_id: str
2830
verification_url: Optional[str] = None
2931
student_name: Optional[str] = None
3032
course_title: Optional[str] = None
33+
course_link: Optional[str] = None
3134
completion_date: Optional[str] = None
3235
duration_hours: Optional[int] = None
3336
issuer: Optional[str] = None
@@ -39,5 +42,10 @@ class CertificateVerificationResponse(BaseModel):
3942
course_level: Optional[str] = None
4043
course_format: Optional[str] = None
4144
instruction_language: Optional[str] = None
45+
46+
47+
class CertificateDeleteResponse(BaseModel):
48+
message: str
49+
certificate_id: str
4250

4351
# Revocation support removed: no revoke schema

backend/scripts/create_certificate.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ def main():
4848
course_level = input("Course level (e.g. Master-level, Bachelor-level, High School-level): ")
4949
course_format = input("Course format (e.g. Online (via Zoom), In-person, Hybrid): ")
5050
instruction_language = input("Instruction language (e.g. English, German, Arabic): ")
51+
course_link = input("Course link (optional, e.g. https://...): ").strip() or None
5152
cert_in = schemas.CertificateCreate(
5253
student_name=student_name,
5354
course_title=course_title,
@@ -58,6 +59,8 @@ def main():
5859
course_level=course_level,
5960
course_format=course_format,
6061
instruction_language=instruction_language
62+
,
63+
course_link=course_link
6164
)
6265
cert = crud.create_certificate(db, cert_in)
6366
print(f"Created certificate: {cert.certificate_id}")

backend/scripts/view_database.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import os
2+
import sys
3+
4+
from dotenv import load_dotenv
5+
from sqlalchemy.orm import Session
6+
7+
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
8+
9+
from app.database import SessionLocal
10+
from app.models import Certificate
11+
12+
13+
load_dotenv()
14+
15+
16+
def view_database(limit: int = 50):
17+
db: Session = SessionLocal()
18+
try:
19+
certificates = (
20+
db.query(Certificate)
21+
.order_by(Certificate.created_at.desc())
22+
.limit(limit)
23+
.all()
24+
)
25+
26+
if not certificates:
27+
print("No certificates found in the database.")
28+
return
29+
30+
print(f"\nShowing up to {limit} certificates:\n")
31+
32+
for cert in certificates:
33+
print("=" * 50)
34+
print(f"Certificate ID : {cert.certificate_id}")
35+
print(f"Student Name : {cert.student_name}")
36+
print(f"Course Title : {cert.course_title}")
37+
print(f"Completion Date: {cert.completion_date}")
38+
print(f"Duration : {cert.duration_hours} hours")
39+
print(f"Issuer : {cert.issuer}")
40+
print(f"Instructor : {cert.instructor}")
41+
print(f"Course Link : {cert.course_link or '-'}")
42+
print(f"Status : {getattr(cert, 'status', 'valid')}")
43+
print(f"Created At : {cert.created_at}")
44+
print("=" * 50)
45+
46+
except Exception as e:
47+
print("Error while fetching data:")
48+
print(e)
49+
finally:
50+
db.close()
51+
52+
53+
if __name__ == "__main__":
54+
view_database()

0 commit comments

Comments
 (0)