Spaces:
Configuration error
Configuration error
| """ | |
| Register curriculum document metadata in Firestore. | |
| Populates the curriculumDocuments collection so the app can display | |
| lessons mapped to their source PDFs before ingestion. | |
| Run: python backend/scripts/register_firestore_metadata.py | |
| """ | |
| from __future__ import annotations | |
| import os | |
| import sys | |
| from pathlib import Path | |
| sys.path.insert(0, str(Path(__file__).resolve().parents[1])) | |
| def _get_firestore_client(): | |
| try: | |
| import firebase_admin | |
| from firebase_admin import firestore | |
| if not firebase_admin._apps: | |
| sa_json = os.getenv("FIREBASE_SERVICE_ACCOUNT_JSON") | |
| sa_file = os.getenv("FIREBASE_SERVICE_ACCOUNT_FILE") | |
| bucket_name = os.getenv("FIREBASE_STORAGE_BUCKET", "mathpulse-ai-2026.firebasestorage.app") | |
| if sa_json: | |
| import json as _json | |
| from firebase_admin import credentials | |
| creds = credentials.Certificate(_json.loads(sa_json)) | |
| firebase_admin.initialize_app(creds, {"storageBucket": bucket_name}) | |
| elif sa_file and Path(sa_file).exists(): | |
| from firebase_admin import credentials | |
| creds = credentials.Certificate(sa_file) | |
| firebase_admin.initialize_app(creds, {"storageBucket": bucket_name}) | |
| else: | |
| firebase_admin.initialize_app(options={"storageBucket": bucket_name}) | |
| return firestore.client() | |
| except Exception as e: | |
| print(f"Firestore init failed: {e}") | |
| return None | |
| CURRICULUM_DOCUMENTS = [ | |
| { | |
| "id": "gm_lesson_1", | |
| "moduleId": "gm-q1-business-finance", | |
| "lessonId": "gm-q1-bf-1", | |
| "title": "Represent business transactions and financial goals using variables and equations.", | |
| "subject": "General Mathematics", | |
| "subjectId": "gen-math", | |
| "quarter": 1, | |
| "competencyCode": "GM11-BF-1", | |
| "learningCompetency": "Represent business transactions and financial goals using variables and equations.", | |
| "storagePath": "curriculum/general_math/GENERAL-MATHEMATICS-1.pdf", | |
| "status": "uploaded", | |
| }, | |
| { | |
| "id": "gm_navotas_lesson_1", | |
| "moduleId": "gm-q1-patterns-sequences-series", | |
| "lessonId": "gm-q1-pss-1", | |
| "title": "Identify and describe arithmetic and geometric patterns in data.", | |
| "subject": "General Mathematics", | |
| "subjectId": "gen-math", | |
| "quarter": 1, | |
| "competencyCode": "GM11-PSS-1", | |
| "learningCompetency": "Identify and describe arithmetic and geometric patterns in data.", | |
| "storagePath": "curriculum/gen_math_sdo/SDO_Navotas_Gen.Math_SHS_1stSem.FV.pdf", | |
| "status": "uploaded", | |
| }, | |
| { | |
| "id": "bm_lesson_1", | |
| "moduleId": "bm-q1-business-math", | |
| "lessonId": "bm-q1-1", | |
| "title": "Translate verbal phrases to mathematical expressions; model business scenarios using linear equations and inequalities.", | |
| "subject": "Business Mathematics", | |
| "subjectId": "business-math", | |
| "quarter": 1, | |
| "competencyCode": "ABM_BM11BS-Ia-b-1", | |
| "learningCompetency": "Translate verbal phrases to mathematical expressions; model business scenarios using linear equations and inequalities.", | |
| "storagePath": "curriculum/business_math/SDO_Navotas_Bus.Math_SHS_1stSem.FV.pdf", | |
| "status": "uploaded", | |
| }, | |
| { | |
| "id": "stat_lesson_1", | |
| "moduleId": "stat-q1-probability", | |
| "lessonId": "stat-q1-1", | |
| "title": "Define and describe random variables and their types.", | |
| "subject": "Statistics and Probability", | |
| "subjectId": "stats-prob", | |
| "quarter": 1, | |
| "competencyCode": "SP_SHS11-Ia-1", | |
| "learningCompetency": "Define and describe random variables and their types.", | |
| "storagePath": "curriculum/stat_prob/SDO_Navotas_STAT_PROB_SHS_1stSem.FV.pdf", | |
| "status": "uploaded", | |
| }, | |
| { | |
| "id": "fm1_lesson_1", | |
| "moduleId": "fm1-q1-counting", | |
| "lessonId": "fm1-q1-fpc-1", | |
| "title": "Apply the fundamental counting principle in contextual problems.", | |
| "subject": "Finite Mathematics 1", | |
| "subjectId": "finite-math-1", | |
| "quarter": 1, | |
| "competencyCode": "FM1-SHS11-Ia-1", | |
| "learningCompetency": "Apply the fundamental counting principle in contextual problems.", | |
| "storagePath": "curriculum/finite_math/Finite-Mathematics-1-1.pdf", | |
| "status": "uploaded", | |
| }, | |
| { | |
| "id": "fm2_lesson_1", | |
| "moduleId": "fm2-q1-matrices", | |
| "lessonId": "fm2-q1-matrices-1", | |
| "title": "Represent contextual data using matrix notation.", | |
| "subject": "Finite Mathematics 2", | |
| "subjectId": "finite-math-2", | |
| "quarter": 1, | |
| "competencyCode": "FM2-SHS11-Ia-1", | |
| "learningCompetency": "Represent contextual data using matrix notation.", | |
| "storagePath": "curriculum/finite_math/Finite-Mathematics-2-1.pdf", | |
| "status": "uploaded", | |
| }, | |
| { | |
| "id": "org_mgmt_lesson_1", | |
| "moduleId": "org-mgmt-q1", | |
| "lessonId": "org-mgmt-q1-1", | |
| "title": "Understand the fundamental concepts of organization and management.", | |
| "subject": "Organization and Management", | |
| "subjectId": "org-mgmt", | |
| "quarter": 1, | |
| "competencyCode": "ABM_OM11-Ia-1", | |
| "learningCompetency": "Understand the fundamental concepts of organization and management.", | |
| "storagePath": "curriculum/org_mgmt/SDO_Navotas_SHS_ABM_OrgAndMngt_FirstSem_FV.pdf", | |
| "status": "uploaded", | |
| }, | |
| ] | |
| def register_metadata(force: bool = False): | |
| db = _get_firestore_client() | |
| if db is None: | |
| print("ERROR: Cannot connect to Firestore. Check credentials.") | |
| print("Set FIREBASE_SERVICE_ACCOUNT_JSON or place mathpulse-sa.json in backend/ directory.") | |
| return | |
| print("Connected to Firestore.") | |
| print("-" * 50) | |
| registered = 0 | |
| skipped = 0 | |
| updated = 0 | |
| for doc in CURRICULUM_DOCUMENTS: | |
| doc_id = doc["id"] | |
| doc_ref = db.collection("curriculumDocuments").document(doc_id) | |
| existing = doc_ref.get() | |
| if existing.exists and not force: | |
| print(f"[SKIP] {doc_id} already registered") | |
| skipped += 1 | |
| continue | |
| if existing.exists and force: | |
| updated += 1 | |
| else: | |
| registered += 1 | |
| data = { | |
| **doc, | |
| "uploadedAt": None, | |
| } | |
| doc_ref.set(data, merge=True) | |
| print(f"[OK] {'Updated' if force and existing.exists else 'Registered'} {doc_id} -> {doc.get('storagePath')}") | |
| print("-" * 50) | |
| print(f"Done: {registered} registered, {skipped} skipped, {updated} updated.") | |
| if __name__ == "__main__": | |
| import argparse | |
| parser = argparse.ArgumentParser(description="Register curriculum document metadata in Firestore") | |
| parser.add_argument("--force", action="store_true", help="Overwrite existing records") | |
| args = parser.parse_args() | |
| register_metadata(force=args.force) |