Download backend/models.py from Devashishraghav/gujarat-reading-programv2: direct link, hf CLI and curl.
- Browser
- Download file 15.4 kB
-
https://huggingface.co/spaces/Devashishraghav/gujarat-reading-programv2/resolve/main/backend/models.py
- Command line
-
hf download hf://spaces/Devashishraghav/gujarat-reading-programv2/backend/models.py
-
curl -L -o models.py https://huggingface.co/spaces/Devashishraghav/gujarat-reading-programv2/resolve/main/backend/models.py
15.4 kB
| """ | |
| DRP Backend β SQLAlchemy Models | |
| All 12+ tables as defined in the PRD and implementation plan. | |
| """ | |
| import uuid | |
| from datetime import datetime | |
| from sqlalchemy import ( | |
| Column, String, Integer, Float, Boolean, DateTime, Text, | |
| ForeignKey, JSON | |
| ) | |
| from sqlalchemy.orm import relationship | |
| from database import Base | |
| def generate_uuid(): | |
| return str(uuid.uuid4()) | |
| # --------------------------------------------------------------------------- | |
| # Geographic / Organisational Hierarchy | |
| # --------------------------------------------------------------------------- | |
| class Programme(Base): | |
| __tablename__ = "programme" | |
| programme_id = Column(String, primary_key=True, default=generate_uuid) | |
| name = Column(String, nullable=False) | |
| state_code = Column(String, nullable=False) | |
| year = Column(Integer, nullable=False) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| schools = relationship("School", back_populates="programme") | |
| class District(Base): | |
| __tablename__ = "district" | |
| district_id = Column(String, primary_key=True, default=generate_uuid) | |
| name = Column(String, nullable=False) | |
| state_code = Column(String, nullable=False) | |
| schools = relationship("School", back_populates="district") | |
| class School(Base): | |
| __tablename__ = "school" | |
| school_id = Column(String, primary_key=True, default=generate_uuid) | |
| udise_code = Column(String, unique=True, nullable=False) | |
| name = Column(String, nullable=False) | |
| district_id = Column(String, ForeignKey("district.district_id")) | |
| block = Column(String) | |
| programme_id = Column(String, ForeignKey("programme.programme_id")) | |
| whatsapp_group_link = Column(String, nullable=True) # For teacher onboarding | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| programme = relationship("Programme", back_populates="schools") | |
| district = relationship("District", back_populates="schools") | |
| classes = relationship("ClassAccount", back_populates="school") | |
| teachers = relationship("TeacherAccount", back_populates="school") | |
| # --------------------------------------------------------------------------- | |
| # Class & Teacher | |
| # --------------------------------------------------------------------------- | |
| class ClassAccount(Base): | |
| __tablename__ = "class_account" | |
| class_id = Column(String, primary_key=True, default=generate_uuid) | |
| school_id = Column(String, ForeignKey("school.school_id"), nullable=False) | |
| grade = Column(Integer, nullable=False) | |
| section = Column(String, nullable=False) | |
| year = Column(Integer, nullable=False) | |
| state = Column(String, default="not_started") # not_started | in_progress | completed | |
| current_cluster_id = Column(String, ForeignKey("cluster.cluster_id"), nullable=True) | |
| reading_level = Column(String, nullable=True) # Set during level selection | |
| whatsapp_group_link = Column(String, nullable=True) # Class-specific link | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| school = relationship("School", back_populates="classes") | |
| journey = relationship("ClassJourney", back_populates="class_account", uselist=False) | |
| sessions = relationship("SessionLog", back_populates="class_account") | |
| achievements = relationship("Achievement", back_populates="class_account") | |
| teacher_mappings = relationship("TeacherClassMapping", back_populates="class_account") | |
| class TeacherAccount(Base): | |
| __tablename__ = "teacher_account" | |
| teacher_id = Column(String, primary_key=True, default=generate_uuid) | |
| name = Column(String, nullable=False) | |
| mobile_hash = Column(String, nullable=True) | |
| phone = Column(String, nullable=True) # For prototype display | |
| email = Column(String, unique=True, nullable=True) # For email login | |
| password_hash = Column(String, nullable=True) # For email login | |
| school_id = Column(String, ForeignKey("school.school_id"), nullable=True) | |
| role = Column(String, default="teacher") # teacher | substitute | |
| activation_token = Column(String, unique=True, nullable=True) | |
| is_active = Column(Boolean, default=False) | |
| has_seen_onboarding = Column(Boolean, default=False) # Onboarding wizard flag | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| school = relationship("School", back_populates="teachers") | |
| class_mappings = relationship("TeacherClassMapping", back_populates="teacher") | |
| sessions = relationship("SessionLog", back_populates="teacher") | |
| class TeacherClassMapping(Base): | |
| __tablename__ = "teacher_class_mapping" | |
| id = Column(String, primary_key=True, default=generate_uuid) | |
| teacher_id = Column(String, ForeignKey("teacher_account.teacher_id"), nullable=False) | |
| class_id = Column(String, ForeignKey("class_account.class_id"), nullable=False) | |
| role = Column(String, default="primary") # primary | substitute | |
| is_default = Column(Boolean, default=False) | |
| teacher = relationship("TeacherAccount", back_populates="class_mappings") | |
| class_account = relationship("ClassAccount", back_populates="teacher_mappings") | |
| # --------------------------------------------------------------------------- | |
| # Content: Books & Clusters | |
| # --------------------------------------------------------------------------- | |
| class Book(Base): | |
| __tablename__ = "book" | |
| book_id = Column(String, primary_key=True, default=generate_uuid) | |
| title = Column(String, nullable=False) | |
| author = Column(String) | |
| illustrator = Column(String) | |
| level = Column(Integer, nullable=False) # 1, 2, 3, 4 | |
| theme = Column(String, nullable=False) # Animals, Nature, Friendship, etc. | |
| language = Column(String, default="English") | |
| cover_url = Column(String) | |
| has_readalong = Column(Boolean, default=False) | |
| pages = Column(JSON, default=list) # List of {page_num, text, image_url} | |
| activity_lets_talk = Column(Text, nullable=True) # Discussion prompt (not scored) | |
| activity_lets_understand = Column(JSON, nullable=True) # MCQ: {question, options[], correct} | |
| activity_lets_play = Column(JSON, nullable=True) # MCQ/rhyme/SEL: {question, options[], correct} | |
| read_count = Column(Integer, default=0) | |
| class Cluster(Base): | |
| __tablename__ = "cluster" | |
| cluster_id = Column(String, primary_key=True, default=generate_uuid) | |
| grade = Column(Integer, nullable=False) | |
| level = Column(Integer, nullable=False) | |
| theme = Column(String, nullable=False) | |
| book_ids = Column(JSON, nullable=False) # List of 3 book_ids | |
| connecting_thread = Column(String, nullable=True) # Narrative thread tying the 3 books | |
| secondary_theme = Column(String, nullable=True) # Fallback if insufficient books | |
| # --------------------------------------------------------------------------- | |
| # Journey & Progress | |
| # --------------------------------------------------------------------------- | |
| class ClassJourney(Base): | |
| __tablename__ = "class_journey" | |
| journey_id = Column(String, primary_key=True, default=generate_uuid) | |
| class_id = Column(String, ForeignKey("class_account.class_id"), unique=True, nullable=False) | |
| cluster_sequence = Column(JSON, default=list) # Ordered list of cluster_ids | |
| completed_cluster_ids = Column(JSON, default=list) # Subset of cluster_sequence | |
| current_book_index = Column(Integer, default=0) # 0-2 within current cluster | |
| total_books_read = Column(Integer, default=0) | |
| class_account = relationship("ClassAccount", back_populates="journey") | |
| class SessionLog(Base): | |
| __tablename__ = "session_log" | |
| session_id = Column(String, primary_key=True, default=generate_uuid) | |
| class_id = Column(String, ForeignKey("class_account.class_id"), nullable=False) | |
| teacher_id = Column(String, ForeignKey("teacher_account.teacher_id"), nullable=True) | |
| substitute_name = Column(String, nullable=True) | |
| book_id = Column(String, ForeignKey("book.book_id"), nullable=False) | |
| cluster_id = Column(String, ForeignKey("cluster.cluster_id"), nullable=False) | |
| timestamp = Column(DateTime, default=datetime.utcnow) | |
| device_type = Column(String, default="web") | |
| readalong_done = Column(Boolean, default=False) | |
| activity_submitted = Column(Boolean, default=False) | |
| completed = Column(Boolean, default=False) | |
| class_account = relationship("ClassAccount", back_populates="sessions") | |
| teacher = relationship("TeacherAccount", back_populates="sessions") | |
| activity_submissions = relationship("ActivitySubmission", back_populates="session") | |
| feedback = relationship("Feedback", back_populates="session", uselist=False) | |
| class ActivitySubmission(Base): | |
| __tablename__ = "activity_submission" | |
| submission_id = Column(String, primary_key=True, default=generate_uuid) | |
| session_id = Column(String, ForeignKey("session_log.session_id"), nullable=False) | |
| activity_type = Column(String, nullable=False) # lets_understand | lets_play | |
| selected_option = Column(String, nullable=False) | |
| is_correct = Column(Boolean, nullable=False) | |
| score = Column(Float, default=0.0) | |
| submitted_at = Column(DateTime, default=datetime.utcnow) | |
| session = relationship("SessionLog", back_populates="activity_submissions") | |
| class Feedback(Base): | |
| __tablename__ = "feedback" | |
| feedback_id = Column(String, primary_key=True, default=generate_uuid) | |
| session_id = Column(String, ForeignKey("session_log.session_id"), unique=True, nullable=False) | |
| feedback_emoji = Column(String, nullable=True) # e.g., π, π, π | |
| feedback_quality = Column(String, nullable=True) # e.g., excellent, good, needs_work | |
| session = relationship("SessionLog", back_populates="feedback") | |
| class Achievement(Base): | |
| __tablename__ = "achievement" | |
| achievement_id = Column(String, primary_key=True, default=generate_uuid) | |
| class_id = Column(String, ForeignKey("class_account.class_id"), nullable=False) | |
| type = Column(String, nullable=False) # cluster_complete | programme_complete | |
| badge_key = Column(String, nullable=True) | |
| earned_at = Column(DateTime, default=datetime.utcnow) | |
| class_account = relationship("ClassAccount", back_populates="achievements") | |
| # --------------------------------------------------------------------------- | |
| # Admin & Programme Team | |
| # --------------------------------------------------------------------------- | |
| class AdminAccount(Base): | |
| __tablename__ = "admin_account" | |
| admin_id = Column(String, primary_key=True, default=generate_uuid) | |
| name = Column(String, nullable=False) | |
| email = Column(String, unique=True, nullable=False) | |
| password_hash = Column(String, nullable=False) | |
| role = Column(String, nullable=False) # school_admin | district_admin | state_admin | programme_team | |
| school_id = Column(String, ForeignKey("school.school_id"), nullable=True) | |
| district_id = Column(String, ForeignKey("district.district_id"), nullable=True) | |
| state_code = Column(String, nullable=True) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| class EscalationTicket(Base): | |
| __tablename__ = "escalation_ticket" | |
| ticket_id = Column(String, primary_key=True, default=generate_uuid) | |
| type = Column(String, nullable=False) # content | technical | access | other | |
| severity = Column(String, default="medium") # low | medium | high | critical | |
| school_id = Column(String, ForeignKey("school.school_id"), nullable=True) | |
| class_id = Column(String, ForeignKey("class_account.class_id"), nullable=True) | |
| description = Column(Text, nullable=False) | |
| status = Column(String, default="open") # open | in_progress | resolved | closed | |
| created_by = Column(String, nullable=True) | |
| assigned_to = Column(String, nullable=True) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| resolved_at = Column(DateTime, nullable=True) | |
| class SystemHealthLog(Base): | |
| __tablename__ = "system_health_log" | |
| log_id = Column(String, primary_key=True, default=generate_uuid) | |
| timestamp = Column(DateTime, default=datetime.utcnow) | |
| api_latency_ms = Column(Float, default=0.0) | |
| error_count = Column(Integer, default=0) | |
| active_sessions = Column(Integer, default=0) | |
| sync_queue_depth = Column(Integer, default=0) | |
| uptime_percent = Column(Float, default=100.0) | |
| class EventLog(Base): | |
| __tablename__ = "event_log" | |
| event_id = Column(String, primary_key=True, default=generate_uuid) | |
| event_type = Column(String, nullable=False) # page_view | book_open | activity_submit | etc. | |
| actor_type = Column(String, nullable=True) # teacher | admin | system | |
| actor_id = Column(String, nullable=True) | |
| metadata_json = Column(JSON, nullable=True) | |
| timestamp = Column(DateTime, default=datetime.utcnow) | |
| class Notification(Base): | |
| __tablename__ = "notification" | |
| notification_id = Column(String, primary_key=True, default=generate_uuid) | |
| teacher_id = Column(String, ForeignKey("teacher_account.teacher_id"), nullable=True) | |
| class_id = Column(String, ForeignKey("class_account.class_id"), nullable=True) | |
| type = Column(String, nullable=False) # reminder | nudge | alert | |
| message = Column(Text) | |
| status = Column(String, default="pending") # pending | sent | read | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| # --------------------------------------------------------------------------- | |
| # Field Staff | |
| # --------------------------------------------------------------------------- | |
| class FieldStaff(Base): | |
| __tablename__ = "field_staff" | |
| staff_id = Column(String, primary_key=True, default=generate_uuid) | |
| name = Column(String, nullable=False) | |
| phone = Column(String, nullable=True) | |
| email = Column(String, unique=True, nullable=False) | |
| password_hash = Column(String, nullable=False) | |
| district_id = Column(String, ForeignKey("district.district_id"), nullable=False) | |
| assigned_blocks = Column(JSON, default=list) # List of block names | |
| is_active = Column(Boolean, default=True) | |
| created_at = Column(DateTime, default=datetime.utcnow) | |
| school_mappings = relationship("SchoolStaffMapping", back_populates="staff") | |
| class SchoolStaffMapping(Base): | |
| __tablename__ = "school_staff_mapping" | |
| id = Column(String, primary_key=True, default=generate_uuid) | |
| staff_id = Column(String, ForeignKey("field_staff.staff_id"), nullable=False) | |
| school_id = Column(String, ForeignKey("school.school_id"), nullable=False) | |
| is_primary = Column(Boolean, default=True) | |
| staff = relationship("FieldStaff", back_populates="school_mappings") | |
| class TrainingLog(Base): | |
| __tablename__ = "training_log" | |
| log_id = Column(String, primary_key=True, default=generate_uuid) | |
| staff_id = Column(String, ForeignKey("field_staff.staff_id"), nullable=False) | |
| school_id = Column(String, ForeignKey("school.school_id"), nullable=False) | |
| date = Column(DateTime, default=datetime.utcnow) | |
| teachers_trained_count = Column(Integer, default=0) | |
| notes = Column(Text, nullable=True) | |
| class SupportLog(Base): | |
| __tablename__ = "support_log" | |
| log_id = Column(String, primary_key=True, default=generate_uuid) | |
| staff_id = Column(String, ForeignKey("field_staff.staff_id"), nullable=False) | |
| teacher_id = Column(String, ForeignKey("teacher_account.teacher_id"), nullable=True) | |
| issue_type = Column(String, nullable=False) # login | technical | content | process | device | |
| description = Column(Text, nullable=False) | |
| resolution = Column(Text, nullable=True) | |
| timestamp = Column(DateTime, default=datetime.utcnow) | |