Initial certificate system

This commit is contained in:
nelso
2026-06-06 19:32:24 +08:00
commit ce4ed6213b
105 changed files with 9133 additions and 0 deletions

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,13 @@
from pydantic import BaseModel, Field
class LoginRequest(BaseModel):
username: str = Field(min_length=1, max_length=64)
password: str = Field(min_length=1, max_length=128)
class LoginResponse(BaseModel):
access_token: str
token_type: str = "bearer"
role_code: str
username: str

View File

@@ -0,0 +1,39 @@
from datetime import date, datetime
from pydantic import BaseModel, Field, field_validator
class CertificateCreate(BaseModel):
learner_id: int
project_code: str = Field(min_length=2, max_length=16)
certificate_name: str | None = Field(default=None, max_length=128)
class_name: str | None = Field(default=None, max_length=128)
course_name: str | None = Field(default=None, max_length=128)
stage_name: str | None = Field(default=None, max_length=128)
issue_date: date
issuer_name: str = Field(min_length=1, max_length=128)
remark: str | None = None
@field_validator("project_code")
@classmethod
def normalize_project_code(cls, value: str) -> str:
return value.strip().upper()
class CertificateOut(BaseModel):
id: int
learner_id: int
project_code: str
certificate_no: str
certificate_name: str
class_name: str | None
course_name: str | None
stage_name: str | None
issue_date: date
issuer_name: str
status: str
pdf_status: str
created_at: datetime
updated_at: datetime
model_config = {"from_attributes": True}

View File

@@ -0,0 +1,18 @@
from datetime import datetime
from pydantic import BaseModel
class ImportBatchOut(BaseModel):
id: int
filename: str
status: str
total_rows: int
valid_rows: int
failed_rows: int
conflict_rows: int
error_report_path: str | None
created_at: datetime
updated_at: datetime
model_config = {"from_attributes": True}

View File

@@ -0,0 +1,31 @@
from datetime import datetime
from pydantic import BaseModel, Field
class LearnerCreate(BaseModel):
phone: str = Field(min_length=6, max_length=32)
current_name: str = Field(min_length=1, max_length=64)
student_no: str | None = Field(default=None, max_length=64)
remark: str | None = None
class LearnerUpdate(BaseModel):
phone: str = Field(min_length=6, max_length=32)
current_name: str = Field(min_length=1, max_length=64)
student_no: str | None = Field(default=None, max_length=64)
status: str = Field(default="active", pattern="^(active|disabled|deleted)$")
remark: str | None = None
class LearnerOut(BaseModel):
id: int
phone: str
current_name: str
student_no: str | None
status: str
remark: str | None
created_at: datetime
updated_at: datetime
model_config = {"from_attributes": True}

View File

@@ -0,0 +1,21 @@
from datetime import datetime
from pydantic import BaseModel
class OperationLogOut(BaseModel):
id: int
admin_user_id: int | None
action: str
action_label: str | None = None
object_type: str
object_label: str | None = None
object_id: str | None
ip_address: str | None
detail_json: str | None
created_at: datetime
risk: str | None = None
risk_label: str | None = None
summary: str | None = None
model_config = {"from_attributes": True}

View File

@@ -0,0 +1,57 @@
from datetime import datetime
from pydantic import BaseModel, Field, field_validator
class ProjectCourseCreate(BaseModel):
code: str = Field(min_length=2, max_length=16)
name: str = Field(min_length=1, max_length=128)
default_certificate_name: str | None = Field(default=None, max_length=128)
default_course_name: str | None = Field(default=None, max_length=128)
default_stage_name: str | None = Field(default=None, max_length=128)
default_issuer_name: str = Field(default="本公司", min_length=1, max_length=128)
@field_validator("code")
@classmethod
def normalize_code(cls, value: str) -> str:
return value.strip().upper()
@field_validator("default_certificate_name", "default_course_name", "default_stage_name")
@classmethod
def empty_to_none(cls, value: str | None) -> str | None:
if value is None:
return None
text = value.strip()
return text or None
class ProjectCourseUpdate(BaseModel):
name: str | None = Field(default=None, min_length=1, max_length=128)
default_certificate_name: str | None = Field(default=None, max_length=128)
default_course_name: str | None = Field(default=None, max_length=128)
default_stage_name: str | None = Field(default=None, max_length=128)
default_issuer_name: str | None = Field(default=None, min_length=1, max_length=128)
status: str | None = Field(default=None, pattern="^(active|disabled)$")
@field_validator("default_certificate_name", "default_course_name", "default_stage_name")
@classmethod
def empty_to_none(cls, value: str | None) -> str | None:
if value is None:
return None
text = value.strip()
return text or None
class ProjectCourseOut(BaseModel):
id: int
code: str
name: str
default_certificate_name: str
default_course_name: str | None
default_stage_name: str | None
default_issuer_name: str
status: str
created_at: datetime
updated_at: datetime
model_config = {"from_attributes": True}