"""Course records (seeded), professor settings, announcements.""" from __future__ import annotations from typing import Any from sqlalchemy import select from app.core.config import get_settings from app.db import SessionLocal from app.models import Course SEED = { "IMM1003": { "title": "Éléments d'évaluation immobilière", "site": "https://www.uqo-imm1003.app", "modules": [ "Introduction à l'évaluation immobilière", "Le cadre professionnel au Québec", "Les principes fondamentaux de l'évaluation", "Le marché immobilier québécois", "Collecte et analyse des données", "La valeur : concepts et types", "Examen mi-session : révision des blocs 1 et 2", "La méthode de comparaison — Partie 1", "La méthode de comparaison — Partie 2", "La méthode du coût", "La méthode du revenu — Partie 1", "La méthode du revenu — Partie 2", "Le rapport d'évaluation", "Révision générale et cas intégrateur", ], "suggestions": [ "Explique-moi les 8 étapes du processus d'évaluation", "Différence entre valeur marchande et valeur d'usage ?", "Quiz sur les principes de la valeur", "Comment ajuster des comparables vers le sujet ?", "Crée un Excel de grille de comparables ajustés", ], }, "IMM1033": { "title": "Méthodes du coût en évaluation immobilière", "site": "https://www.uqo-imm1033.app", "modules": [ "Introduction à la méthode du coût", "Cadre conceptuel et terminologie", "Méthodes d'évaluation du terrain", "Analyse du terrain et ajustements", "Coût de reproduction et coût de remplacement", "Méthodes d'estimation des coûts", "Coûts directs de construction", "Coûts indirects et profit entrepreneurial", "Concepts de dépréciation", "Dépréciation physique", "Dépréciation fonctionnelle", "Dépréciation économique (externe)", "Applications spécialisées", "Synthèse et révision", ], "suggestions": [ "Calcule la dépréciation par la méthode âge-vie", "Crée un Excel de la méthode du coût pour un plex", "Coût de reproduction vs remplacement ?", "Quiz sur les types de dépréciation", "Comment estimer la valeur d'un terrain par extraction ?", ], }, } async def seed_courses() -> None: s = get_settings() async with SessionLocal() as session: for code in s.courses: existing = await session.scalar(select(Course).where(Course.code == code)) meta = SEED.get(code, {"title": code, "modules": [], "suggestions": []}) if existing is None: session.add(Course(code=code, title=meta["title"], term=s.TERM_LABEL, syllabus={"modules": meta["modules"], "suggestions": meta["suggestions"], "site": meta.get("site", ""), "deadlines": []}, settings={"tools_enabled": None, "model_primary": None})) await session.commit() async def list_courses(include_private: bool = False) -> list[dict[str, Any]]: async with SessionLocal() as session: rows = (await session.execute(select(Course).where(Course.active.is_(True)) .order_by(Course.code))).scalars() out = [] for c in rows: d: dict[str, Any] = {"code": c.code, "title": c.title, "term": c.term, "modules": c.syllabus.get("modules", []), "suggestions": c.syllabus.get("suggestions", []), "site": c.syllabus.get("site", ""), "deadlines": c.syllabus.get("deadlines", []), "announcement": c.announcement} if include_private: d["extra_system_prompt"] = c.extra_system_prompt d["settings"] = c.settings out.append(d) return out async def get_course(code: str) -> Course | None: async with SessionLocal() as session: return await session.scalar(select(Course).where(Course.code == code.upper())) async def update_course(code: str, data: dict[str, Any]) -> dict[str, Any] | None: async with SessionLocal() as session: c = await session.scalar(select(Course).where(Course.code == code.upper())) if c is None: return None if "extra_system_prompt" in data: c.extra_system_prompt = str(data["extra_system_prompt"] or "")[:6000] if "announcement" in data: c.announcement = str(data["announcement"] or "")[:1000] if "deadlines" in data or "suggestions" in data: syl = dict(c.syllabus) if "deadlines" in data: syl["deadlines"] = list(data["deadlines"] or [])[:20] if "suggestions" in data: syl["suggestions"] = [str(x)[:120] for x in (data["suggestions"] or [])][:8] c.syllabus = syl if "settings" in data: st = dict(c.settings or {}) st.update({k: v for k, v in (data["settings"] or {}).items() if k in {"tools_enabled", "model_primary", "budget_usd", "tone"}}) c.settings = st await session.commit() return {"code": c.code, "extra_system_prompt": c.extra_system_prompt, "announcement": c.announcement, "syllabus": c.syllabus, "settings": c.settings}