254 lines
10 KiB
Python
254 lines
10 KiB
Python
"""Create tables and seed the DEVTeacher placeholder content on first run.
|
||
|
||
Idempotent: if an admin already exists, nothing is seeded. The default admin is
|
||
username ``DEVTeacher`` / password ``DEVTeacher`` (the teacher changes it).
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from datetime import date
|
||
|
||
from sqlalchemy import inspect, text
|
||
from sqlalchemy.orm import Session
|
||
|
||
from app.db import Base, SessionLocal, engine
|
||
from app.models import (
|
||
AdminUser,
|
||
Attendance,
|
||
Course,
|
||
DayMark,
|
||
Enquiry,
|
||
FeePlan,
|
||
Profile,
|
||
Review,
|
||
ScheduleSlot,
|
||
SiteSettings,
|
||
Student,
|
||
Subject,
|
||
Testimonial,
|
||
)
|
||
from app.security import hash_password
|
||
|
||
DEFAULT_ADMIN_USER = "DEVTeacher"
|
||
DEFAULT_ADMIN_PASS = "DEVTeacher"
|
||
|
||
|
||
def _seed(db: Session) -> None:
|
||
db.add(AdminUser(username=DEFAULT_ADMIN_USER, password_hash=hash_password(DEFAULT_ADMIN_PASS)))
|
||
|
||
db.add(
|
||
Profile(
|
||
name="Swati Yadav",
|
||
tagline="Making learning joyful, clear and exam-ready",
|
||
bio=(
|
||
"Hello! I'm Swati Yadav, a passionate tuition teacher with years of experience "
|
||
"helping students build strong fundamentals and real confidence. I focus on "
|
||
"concept clarity, regular practice and personal attention so every student can "
|
||
"reach their full potential — whether the goal is topping the class, cracking "
|
||
"board exams, or simply falling in love with a subject."
|
||
),
|
||
photo_url="",
|
||
qualifications="M.Sc. Mathematics · B.Ed. · Certified Online Educator",
|
||
experience_years=10,
|
||
students_taught=500,
|
||
achievements=(
|
||
"95% of students improved by 2+ grades\n"
|
||
"Mentored 50+ board-exam toppers\n"
|
||
"Personalised study plans for every learner"
|
||
),
|
||
hero_cta="Book a free demo class",
|
||
)
|
||
)
|
||
|
||
subjects = [
|
||
("Mathematics", "Class 6–12", "Algebra, geometry, calculus and problem-solving made simple with step-by-step methods.", "📐", 1),
|
||
("Physics", "Class 9–12", "Concept-first physics with real-life examples, numericals and exam techniques.", "🔬", 2),
|
||
("Chemistry", "Class 9–12", "Organic, inorganic and physical chemistry taught with clarity and easy recall tricks.", "⚗️", 3),
|
||
("English", "Class 6–10", "Grammar, comprehension, writing skills and confident communication.", "📖", 4),
|
||
]
|
||
for name, level, desc, icon, order in subjects:
|
||
db.add(Subject(name=name, level=level, description=desc, mode="Online & Offline", icon=icon, sort_order=order))
|
||
|
||
courses = [
|
||
(
|
||
"Board Exam Crash Course",
|
||
"Mathematics & Science",
|
||
"An intensive revision programme covering the complete syllabus with mock tests, doubt-clearing and previous-year papers.",
|
||
"3 months",
|
||
"Practice tests every week\nPersonal doubt sessions\nComplete syllabus revision",
|
||
1,
|
||
),
|
||
(
|
||
"Foundation Builder",
|
||
"All Subjects",
|
||
"A steady long-term course for younger students that builds strong basics and study habits from the ground up.",
|
||
"Full academic year",
|
||
"Concept-first teaching\nRegular homework & feedback\nMonthly progress reports",
|
||
2,
|
||
),
|
||
(
|
||
"One-on-One Personal Tuition",
|
||
"Chosen Subject",
|
||
"Fully personalised private tuition tailored to a single student's pace, goals and weak areas.",
|
||
"Flexible",
|
||
"Completely customised plan\nFlexible timings\nDedicated attention",
|
||
3,
|
||
),
|
||
]
|
||
for title, subject, desc, duration, highlights, order in courses:
|
||
db.add(
|
||
Course(
|
||
title=title,
|
||
subject=subject,
|
||
description=desc,
|
||
duration=duration,
|
||
mode="Online & Offline",
|
||
highlights=highlights,
|
||
sort_order=order,
|
||
)
|
||
)
|
||
|
||
fees = [
|
||
("Group Batch", "₹1,500", "per month", "Small batches (max 8)\n3 classes a week\nWeekly tests\nStudy material included", False, 1),
|
||
("Premium Batch", "₹2,500", "per month", "Mini batches (max 4)\n5 classes a week\nWeekly tests + doubt sessions\nMonthly progress report", True, 2),
|
||
("1-on-1 Private", "₹4,000", "per month", "Fully personal tuition\nFlexible timings\nCustom study plan\nUnlimited doubt support", False, 3),
|
||
]
|
||
for name, price, period, features, highlighted, order in fees:
|
||
db.add(FeePlan(name=name, price=price, period=period, features=features, highlighted=highlighted, sort_order=order))
|
||
|
||
testimonials = [
|
||
("Aarav Sharma", "Student", "Swati ma'am made maths so easy to understand. My marks jumped from 62 to 91 in just one year!", 5, 1),
|
||
("Meena Gupta", "Parent", "My daughter actually looks forward to her classes now. The personal attention is wonderful.", 5, 2),
|
||
("Rohan Verma", "Student", "The best teacher I've ever had. She explains every concept until it truly clicks.", 5, 3),
|
||
("Kavita Nair", "Parent", "Very disciplined, caring and result-oriented. Highly recommend to every parent.", 5, 4),
|
||
]
|
||
for author, relation, quote, rating, order in testimonials:
|
||
db.add(Testimonial(author_name=author, relation=relation, quote=quote, rating=rating, sort_order=order))
|
||
|
||
db.add(
|
||
SiteSettings(
|
||
address="123 Vidya Nagar, Near City Library, Your City, 000000",
|
||
phone="+91 90000 00000",
|
||
email="hello@swatiyadav.com",
|
||
hours="Mon–Sat, 9:00 AM – 8:00 PM",
|
||
whatsapp="https://wa.me/919000000000",
|
||
instagram="https://instagram.com/",
|
||
youtube="https://youtube.com/",
|
||
facebook="https://facebook.com/",
|
||
footer_text="Empowering students with knowledge, confidence and care.",
|
||
)
|
||
)
|
||
|
||
db.add(
|
||
Enquiry(
|
||
name="Sample Parent",
|
||
email="parent@example.com",
|
||
phone="+91 98765 43210",
|
||
subject_interest="Mathematics",
|
||
message="Hi, I'd like to know the timings for the Class 10 maths batch. Thank you!",
|
||
is_read=False,
|
||
)
|
||
)
|
||
|
||
reviews = [
|
||
("Priya Deshmukh", "Parent", 5, "The weekly progress updates keep me informed and my son is far more confident now.", True),
|
||
("Ananya Rao", "Student", 5, "Doubts are always cleared patiently. Highly recommend her classes!", False),
|
||
]
|
||
for author, relation, rating, message, approved in reviews:
|
||
db.add(Review(author_name=author, relation=relation, rating=rating, message=message, is_approved=approved))
|
||
|
||
db.commit()
|
||
|
||
_seed_students(db)
|
||
|
||
|
||
def _seed_students(db: Session) -> None:
|
||
"""Sample students, schedules and a little attendance for this month."""
|
||
students_data = [
|
||
# name, phone, parent_name, parent_phone, address, subject, fee, slots
|
||
(
|
||
"Aarav Sharma", "+91 98111 22233", "Rakesh Sharma", "+91 98111 00011",
|
||
"12 Green Park, Your City", "Mathematics · Class 10", 1500,
|
||
[(0, "16:00", "17:00"), (2, "16:00", "17:00"), (4, "16:00", "17:00")],
|
||
),
|
||
(
|
||
"Isha Verma", "+91 98222 33344", "Sunita Verma", "+91 98222 00022",
|
||
"45 Lake View, Your City", "Physics · Class 12", 2500,
|
||
[(1, "17:30", "18:30"), (3, "17:30", "18:30")],
|
||
),
|
||
(
|
||
"Rohan Gupta", "+91 98333 44455", "Manoj Gupta", "+91 98333 00033",
|
||
"78 Rose Villa, Your City", "Chemistry · Class 11", 2500,
|
||
[(0, "18:00", "19:00"), (3, "18:00", "19:00"), (5, "10:00", "11:00")],
|
||
),
|
||
(
|
||
"Ananya Nair", "+91 98444 55566", "Kavita Nair", "+91 98444 00044",
|
||
"9 Sunrise Apartments, Your City", "English · Class 8", 1500,
|
||
[(1, "16:00", "17:00"), (4, "16:00", "17:00")],
|
||
),
|
||
]
|
||
|
||
student_objs: list[Student] = []
|
||
for name, phone, pname, pphone, addr, subj, fee, slots in students_data:
|
||
s = Student(
|
||
name=name, phone=phone, parent_name=pname, parent_phone=pphone,
|
||
address=addr, subject=subj, monthly_fee=fee, start_date=date.today(),
|
||
is_active=True, notes="",
|
||
)
|
||
db.add(s)
|
||
db.flush()
|
||
for weekday, start, end in slots:
|
||
db.add(ScheduleSlot(student_id=s.id, weekday=weekday, start_time=start, end_time=end))
|
||
student_objs.append(s)
|
||
|
||
# A little attendance for the first few days of the current month.
|
||
today = date.today()
|
||
statuses = ["present", "present", "absent", "present", "off"]
|
||
for day in range(1, 6):
|
||
try:
|
||
d = date(today.year, today.month, day)
|
||
except ValueError:
|
||
continue
|
||
if d > today:
|
||
break
|
||
for i, s in enumerate(student_objs):
|
||
db.add(Attendance(student_id=s.id, date=d, status=statuses[(day + i) % len(statuses)]))
|
||
|
||
# A sample holiday on the 1st (kept only if not in the future).
|
||
try:
|
||
first = date(today.year, today.month, 1)
|
||
db.add(DayMark(date=first, kind="holiday", note="Month start holiday"))
|
||
except ValueError:
|
||
pass
|
||
|
||
db.commit()
|
||
|
||
|
||
def _ensure_columns() -> None:
|
||
"""Add columns introduced after a table was first created.
|
||
|
||
``create_all`` never alters existing tables, so on databases that already
|
||
have the ``attendance`` table we add the newer ``note`` column by hand.
|
||
"""
|
||
inspector = inspect(engine)
|
||
if "attendance" not in inspector.get_table_names():
|
||
return
|
||
cols = {c["name"] for c in inspector.get_columns("attendance")}
|
||
if "note" not in cols:
|
||
default = "''" if engine.dialect.name != "sqlite" else "''"
|
||
with engine.begin() as conn:
|
||
conn.execute(
|
||
text(f"ALTER TABLE attendance ADD COLUMN note TEXT NOT NULL DEFAULT {default}")
|
||
)
|
||
|
||
|
||
def init_db() -> None:
|
||
Base.metadata.create_all(bind=engine)
|
||
_ensure_columns()
|
||
db = SessionLocal()
|
||
try:
|
||
if db.query(AdminUser).count() == 0:
|
||
_seed(db)
|
||
finally:
|
||
db.close()
|