270 lines
4.6 KiB
Python
270 lines
4.6 KiB
Python
"""Pydantic request/response schemas."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from datetime import date, datetime
|
|
|
|
from pydantic import BaseModel, ConfigDict
|
|
|
|
|
|
class ORMModel(BaseModel):
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
# ---- Auth ----
|
|
class LoginIn(BaseModel):
|
|
username: str
|
|
password: str
|
|
|
|
|
|
class TokenOut(BaseModel):
|
|
access_token: str
|
|
token_type: str = "bearer"
|
|
username: str
|
|
|
|
|
|
class MeOut(BaseModel):
|
|
username: str
|
|
|
|
|
|
class ChangePasswordIn(BaseModel):
|
|
current_password: str
|
|
new_password: str
|
|
|
|
|
|
# ---- Profile ----
|
|
class ProfileIn(BaseModel):
|
|
name: str = ""
|
|
tagline: str = ""
|
|
bio: str = ""
|
|
photo_url: str = ""
|
|
qualifications: str = ""
|
|
experience_years: int = 0
|
|
students_taught: int = 0
|
|
achievements: str = ""
|
|
hero_cta: str = "Book a free demo"
|
|
|
|
|
|
class ProfileOut(ProfileIn, ORMModel):
|
|
id: int
|
|
|
|
|
|
# ---- Subject ----
|
|
class SubjectIn(BaseModel):
|
|
name: str = ""
|
|
level: str = ""
|
|
description: str = ""
|
|
mode: str = "Online & Offline"
|
|
icon: str = "📘"
|
|
sort_order: int = 0
|
|
|
|
|
|
class SubjectOut(SubjectIn, ORMModel):
|
|
id: int
|
|
|
|
|
|
# ---- Course ----
|
|
class CourseIn(BaseModel):
|
|
title: str = ""
|
|
subject: str = ""
|
|
description: str = ""
|
|
duration: str = ""
|
|
mode: str = "Online & Offline"
|
|
highlights: str = ""
|
|
sort_order: int = 0
|
|
|
|
|
|
class CourseOut(CourseIn, ORMModel):
|
|
id: int
|
|
|
|
|
|
# ---- Fee ----
|
|
class FeePlanIn(BaseModel):
|
|
name: str = ""
|
|
price: str = ""
|
|
period: str = "per month"
|
|
features: str = ""
|
|
highlighted: bool = False
|
|
sort_order: int = 0
|
|
|
|
|
|
class FeePlanOut(FeePlanIn, ORMModel):
|
|
id: int
|
|
|
|
|
|
# ---- Testimonial ----
|
|
class TestimonialIn(BaseModel):
|
|
author_name: str = ""
|
|
relation: str = "Student"
|
|
quote: str = ""
|
|
rating: int = 5
|
|
sort_order: int = 0
|
|
|
|
|
|
class TestimonialOut(TestimonialIn, ORMModel):
|
|
id: int
|
|
|
|
|
|
# ---- Settings ----
|
|
class SiteSettingsIn(BaseModel):
|
|
address: str = ""
|
|
phone: str = ""
|
|
email: str = ""
|
|
hours: str = ""
|
|
whatsapp: str = ""
|
|
instagram: str = ""
|
|
youtube: str = ""
|
|
facebook: str = ""
|
|
footer_text: str = ""
|
|
|
|
|
|
class SiteSettingsOut(SiteSettingsIn, ORMModel):
|
|
id: int
|
|
|
|
|
|
# ---- Review (public feedback, moderated) ----
|
|
class ReviewIn(BaseModel):
|
|
author_name: str
|
|
relation: str = "Student"
|
|
rating: int = 5
|
|
message: str
|
|
|
|
|
|
class ReviewOut(ORMModel):
|
|
id: int
|
|
author_name: str
|
|
relation: str
|
|
rating: int
|
|
message: str
|
|
is_approved: bool
|
|
created_at: datetime
|
|
|
|
|
|
class ReviewPatch(BaseModel):
|
|
is_approved: bool
|
|
|
|
|
|
# ---- Enquiry ----
|
|
class EnquiryIn(BaseModel):
|
|
name: str
|
|
email: str = ""
|
|
phone: str = ""
|
|
subject_interest: str = ""
|
|
message: str
|
|
|
|
|
|
class EnquiryOut(ORMModel):
|
|
id: int
|
|
name: str
|
|
email: str
|
|
phone: str
|
|
subject_interest: str
|
|
message: str
|
|
created_at: datetime
|
|
is_read: bool
|
|
|
|
|
|
class EnquiryPatch(BaseModel):
|
|
is_read: bool
|
|
|
|
|
|
# ---- Student management ----
|
|
class ScheduleSlotIn(BaseModel):
|
|
weekday: int = 0 # 0=Mon .. 6=Sun
|
|
start_time: str = ""
|
|
end_time: str = ""
|
|
|
|
|
|
class ScheduleSlotOut(ScheduleSlotIn, ORMModel):
|
|
id: int
|
|
student_id: int
|
|
|
|
|
|
class StudentIn(BaseModel):
|
|
name: str = ""
|
|
phone: str = ""
|
|
parent_name: str = ""
|
|
parent_phone: str = ""
|
|
address: str = ""
|
|
subject: str = ""
|
|
monthly_fee: int = 0
|
|
start_date: date | None = None
|
|
is_active: bool = True
|
|
notes: str = ""
|
|
|
|
|
|
class StudentOut(ORMModel):
|
|
id: int
|
|
name: str
|
|
phone: str
|
|
parent_name: str
|
|
parent_phone: str
|
|
address: str
|
|
subject: str
|
|
monthly_fee: int
|
|
start_date: date
|
|
is_active: bool
|
|
notes: str
|
|
|
|
|
|
class AttendanceIn(BaseModel):
|
|
student_id: int
|
|
date: date
|
|
status: str = "present" # present|absent|off
|
|
note: str = ""
|
|
|
|
|
|
class AttendanceOut(ORMModel):
|
|
id: int
|
|
student_id: int
|
|
date: date
|
|
status: str
|
|
note: str
|
|
|
|
|
|
class AttendanceClearIn(BaseModel):
|
|
student_id: int
|
|
date: date
|
|
|
|
|
|
class DayMarkIn(BaseModel):
|
|
date: date
|
|
kind: str = "holiday" # holiday|class_off
|
|
note: str = ""
|
|
|
|
|
|
class DayMarkOut(ORMModel):
|
|
id: int
|
|
date: date
|
|
kind: str
|
|
note: str
|
|
|
|
|
|
class MonthDataOut(BaseModel):
|
|
attendance: list[AttendanceOut]
|
|
day_marks: list[DayMarkOut]
|
|
|
|
|
|
class TodayEntryOut(BaseModel):
|
|
student_id: int
|
|
student_name: str
|
|
subject: str
|
|
start_time: str
|
|
end_time: str
|
|
|
|
|
|
class StudentSummaryOut(BaseModel):
|
|
student_id: int
|
|
student_name: str
|
|
monthly_fee: int
|
|
present: int
|
|
absent: int
|
|
off: int
|
|
|
|
|
|
class SummaryOut(BaseModel):
|
|
month: str
|
|
active_students: int
|
|
expected_income: int
|
|
students: list[StudentSummaryOut]
|