"""مهاجرت‌های سبک دیتابیس — DDL و تبدیل داده‌های قدیمی؛ همه idempotent. هم main.py (startup) و هم seed.py این‌ها را صدا می‌زنند تا هر مسیر اجرایی دیتابیس موجود را بدون از دست رفتن داده ارتقا دهد. """ from sqlalchemy import text from .database import SessionLocal, engine # جدول‌های مجموعه‌ای که ستون position دارند POSITION_TABLES = [ "services", "projects", "articles", "testimonials", "faqs", "team", "timeline", "stats", "why_us", "investment_models", "process_steps", "offices", "gallery_images", "nav_items", ] def run_ddl_migrations() -> None: """ستون‌های جدید — برای PostgreSQL با ADD COLUMN IF NOT EXISTS.""" if engine.dialect.name != "postgresql": return with engine.begin() as conn: for table in POSITION_TABLES: conn.execute( text(f"ALTER TABLE {table} ADD COLUMN IF NOT EXISTS position INTEGER NOT NULL DEFAULT 0") ) def paragraphs_to_doc(paragraphs: list) -> dict: """تبدیل لیست پاراگراف‌های متنی (فرمت قدیمی بدنه مقاله) به سند TipTap.""" content = [] for para in paragraphs: if isinstance(para, str) and para.strip(): content.append({ "type": "paragraph", "content": [{"type": "text", "text": para}], }) if not content: content = [{"type": "paragraph"}] return {"type": "doc", "content": content} def migrate_article_bodies() -> None: """تبدیل بدنه مقالات از لیست پاراگراف به سند JSON — idempotent.""" from . import models # lazy — جلوگیری از import حلقه‌ای db = SessionLocal() try: changed = 0 for article in db.query(models.Article).all(): if isinstance(article.body, list): article.body = paragraphs_to_doc(article.body) changed += 1 db.commit() if changed: print(f"مقالات تبدیل‌شده به فرمت سند: {changed}") finally: db.close() def run_all() -> None: run_ddl_migrations() migrate_article_bodies()