Kagamicho/cs_chatbot
0
1"""One-shot migration: add `body`, `notes`, `category` fields to cannedReplies docs.2 3- Sets `body` ← old `bodyHtml` (if the doc doesn't already have `body`).4- Sets `notes: None` and `category: None` if those fields are missing.5- Leaves `bodyHtml` and `bodyText` in place (belt-and-suspenders; removable later).6- Idempotent: skips any doc that already has a `body` field.7 8Usage:9 cd apps/chatbot10 PYTHONPATH=. uv run python scripts/migrate_canned_replies_schema.py11"""12from __future__ import annotations13 14import logging15from dotenv import load_dotenv16 17load_dotenv()18logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")19logger = logging.getLogger("migrate-canned-replies")20 21 22def main() -> int:23 from app.firebase import get_db24 25 db = get_db()26 coll = db.collection("cannedReplies")27 28 migrated = 029 skipped = 030 31 for doc_snap in coll.stream():32 data = doc_snap.to_dict() or {}33 34 if "body" in data:35 logger.info("Skip (already migrated): %s id=%s", data.get("title", "?"), doc_snap.id)36 skipped += 137 continue38 39 updates: dict = {}40 updates["body"] = data.get("bodyHtml") or ""41 if "notes" not in data:42 updates["notes"] = None43 if "category" not in data:44 updates["category"] = None45 46 doc_snap.reference.update(updates)47 logger.info(48 "Migrated: %s id=%s body_len=%d",49 data.get("title", "?"),50 doc_snap.id,51 len(updates["body"]),52 )53 migrated += 154 55 logger.info("Migration complete: migrated=%d skipped=%d", migrated, skipped)56 return 057 58 59if __name__ == "__main__":60 raise SystemExit(main())61 