Spaces:
Sleeping
Sleeping
| # modules/database.py | |
| from sqlalchemy import create_engine, Column, Integer, String, Float, Text, ForeignKey, DateTime, Boolean, inspect, text | |
| from sqlalchemy.orm import declarative_base, sessionmaker | |
| from datetime import datetime | |
| import hashlib | |
| import os | |
| from pathlib import Path | |
| # Storage setup | |
| IS_SPACES = os.environ.get('SPACE_ID') is not None | |
| if IS_SPACES: | |
| STORAGE_DIR = Path('/data') | |
| STORAGE_DIR.mkdir(exist_ok=True) | |
| DB_PATH = STORAGE_DIR / 'empower.db' | |
| else: | |
| STORAGE_DIR = Path('.') | |
| DB_PATH = Path('empower.db') | |
| # Database setup | |
| ENGINE = create_engine(f'sqlite:///{DB_PATH}', connect_args={'check_same_thread': False}) | |
| Base = declarative_base() | |
| Session = sessionmaker(bind=ENGINE) | |
| # Models | |
| class User(Base): | |
| __tablename__ = 'users' | |
| id = Column(Integer, primary_key=True) | |
| name = Column(String) | |
| email = Column(String, unique=True) | |
| role = Column(String) | |
| password_hash = Column(String) | |
| subjects_taught = Column(String) | |
| class_teacher_for = Column(String) | |
| gender = Column(String) | |
| phone_number = Column(String) | |
| class Student(Base): | |
| __tablename__ = 'students' | |
| id = Column(Integer, primary_key=True) | |
| name = Column(String) | |
| year = Column(Integer) | |
| class_name = Column(String) | |
| registration_number = Column(String) | |
| subjects = Column(String) | |
| subject_history = Column(Text) | |
| gender = Column(String) | |
| enrollment_date = Column(String) | |
| class AcademicTerm(Base): | |
| __tablename__ = 'academic_terms' | |
| id = Column(Integer, primary_key=True) | |
| year = Column(Integer) | |
| term_number = Column(Integer) | |
| term_name = Column(String) | |
| start_date = Column(String) | |
| end_date = Column(String) | |
| next_term_begins = Column(String) | |
| is_active = Column(Boolean, default=False) | |
| class ComponentMark(Base): | |
| __tablename__ = 'component_marks' | |
| id = Column(Integer, primary_key=True) | |
| student_id = Column(Integer, ForeignKey('students.id')) | |
| subject = Column(String) | |
| term_id = Column(Integer, ForeignKey('academic_terms.id')) | |
| component_type = Column(String) | |
| component_name = Column(String) | |
| score = Column(Float) | |
| total = Column(Float) | |
| submitted_by = Column(Integer, ForeignKey('users.id')) | |
| submitted_at = Column(String, default=lambda: datetime.now().isoformat()) | |
| class Mark(Base): | |
| __tablename__ = 'marks' | |
| id = Column(Integer, primary_key=True) | |
| student_id = Column(Integer, ForeignKey('students.id')) | |
| subject = Column(String) | |
| term_id = Column(Integer, ForeignKey('academic_terms.id')) | |
| coursework_score = Column(Float) | |
| coursework_total = Column(Float) | |
| coursework_out_of_20 = Column(Float) | |
| midterm_score = Column(Float) | |
| midterm_total = Column(Float) | |
| midterm_out_of_20 = Column(Float) | |
| endterm_score = Column(Float) | |
| endterm_total = Column(Float) | |
| endterm_out_of_60 = Column(Float) | |
| total = Column(Float) | |
| grade = Column(String) | |
| comment = Column(Text) | |
| submitted_by = Column(Integer, ForeignKey('users.id')) | |
| submitted_at = Column(String, default=lambda: datetime.now().isoformat()) | |
| class DisciplineReport(Base): | |
| __tablename__ = 'discipline_reports' | |
| id = Column(Integer, primary_key=True) | |
| student_id = Column(Integer, ForeignKey('students.id')) | |
| reported_by = Column(Integer, ForeignKey('users.id')) | |
| incident_date = Column(String) | |
| incident_type = Column(String) | |
| description = Column(Text) | |
| action_taken = Column(Text) | |
| status = Column(String, default="Pending") | |
| admin_notes = Column(Text) | |
| created_at = Column(String, default=lambda: datetime.now().isoformat()) | |
| class ReportDesign(Base): | |
| __tablename__ = 'report_design' | |
| id = Column(Integer, primary_key=True) | |
| school_name = Column(String, default="EMPOWER INTERNATIONAL ACADEMY") | |
| school_subtitle = Column(String, default="A Christian Boarding International School") | |
| school_address = Column(String, default="Nswanjere - Off Kampala-Mityana Road") | |
| school_po_box = Column(String, default="P.O BOX 1030, Kampala-Uganda") | |
| school_phone = Column(String, default="") | |
| school_email = Column(String, default="") | |
| school_website = Column(String, default="") | |
| logo_data = Column(Text) | |
| primary_color = Column(String, default="#8B4513") | |
| report_footer = Column(Text, default="") | |
| class AuditLog(Base): | |
| __tablename__ = 'audit_logs' | |
| id = Column(Integer, primary_key=True) | |
| user_id = Column(Integer, ForeignKey('users.id')) | |
| action = Column(String) | |
| details = Column(Text) | |
| timestamp = Column(DateTime, default=datetime.utcnow) | |
| class ClassroomBehavior(Base): | |
| __tablename__ = 'classroom_behavior' | |
| id = Column(Integer, primary_key=True) | |
| student_id = Column(Integer, ForeignKey('students.id')) | |
| term_id = Column(Integer, ForeignKey('academic_terms.id')) | |
| evaluated_by = Column(Integer, ForeignKey('users.id')) | |
| punctuality = Column(String) | |
| attendance = Column(String) | |
| manners = Column(String) | |
| general_behavior = Column(String) | |
| organisational_skills = Column(String) | |
| adherence_to_uniform = Column(String) | |
| leadership_skills = Column(String) | |
| commitment_to_school = Column(String) | |
| cooperation_with_peers = Column(String) | |
| cooperation_with_staff = Column(String) | |
| participation_in_lessons = Column(String) | |
| completion_of_homework = Column(String) | |
| evaluated_at = Column(String, default=lambda: datetime.now().isoformat()) | |
| class StudentDecision(Base): | |
| __tablename__ = 'student_decisions' | |
| id = Column(Integer, primary_key=True) | |
| student_id = Column(Integer, ForeignKey('students.id')) | |
| term_id = Column(Integer, ForeignKey('academic_terms.id')) | |
| decision = Column(String) | |
| decision_made_by = Column(Integer, ForeignKey('users.id')) | |
| decision_date = Column(String, default=lambda: datetime.now().isoformat()) | |
| notes = Column(Text) | |
| class VisitationDay(Base): | |
| __tablename__ = 'visitation_days' | |
| id = Column(Integer, primary_key=True) | |
| student_id = Column(Integer, ForeignKey('students.id')) | |
| term_id = Column(Integer, ForeignKey('academic_terms.id')) | |
| visitation_date = Column(String) | |
| parent_attended = Column(Boolean, default=False) | |
| report_given = Column(Boolean, default=False) | |
| notes = Column(Text) | |
| created_by = Column(Integer, ForeignKey('users.id')) | |
| created_at = Column(String, default=lambda: datetime.now().isoformat()) | |
| # Helper functions | |
| def update_database_schema(): | |
| """Update database schema with new tables and columns""" | |
| inspector = inspect(ENGINE) | |
| if 'visitation_days' not in inspector.get_table_names(): | |
| VisitationDay.__table__.create(ENGINE) | |
| if 'student_decisions' not in inspector.get_table_names(): | |
| StudentDecision.__table__.create(ENGINE) | |
| if 'component_marks' not in inspector.get_table_names(): | |
| ComponentMark.__table__.create(ENGINE) | |
| def init_database(): | |
| """Initialize database and create all tables""" | |
| Base.metadata.create_all(ENGINE) | |
| update_database_schema() | |
| def init_admin(): | |
| """Create default admin user if not exists""" | |
| session = Session() | |
| admin = session.query(User).filter_by(email='admin').first() | |
| if not admin: | |
| admin = User( | |
| name='System Admin', | |
| email='admin', | |
| role='admin', | |
| password_hash=hashlib.sha256('admin123'.encode()).hexdigest(), | |
| subjects_taught='', | |
| class_teacher_for='', | |
| gender='', | |
| phone_number='' | |
| ) | |
| session.add(admin) | |
| session.commit() | |
| session.close() | |
| def init_report_design(): | |
| """Initialize report design if not exists""" | |
| session = Session() | |
| design = session.query(ReportDesign).first() | |
| if not design: | |
| design = ReportDesign() | |
| session.add(design) | |
| session.commit() | |
| session.close() | |
| def log_audit(session, user_id, action, details=""): | |
| """Log an audit entry""" | |
| log = AuditLog(user_id=user_id, action=action, details=details) | |
| session.add(log) | |
| session.commit() |