from __future__ import annotations import argparse import json from pathlib import Path from app.audit.logging import audit_event from app.db.bootstrap import create_all_tables from app.db.session import SessionLocal from app.db.models import User from app.security.api_keys import authenticate_api_key from app.settings import settings from app.mailer.persistence.campaigns import create_campaign_version_from_json, validate_campaign_version, build_campaign_version def main() -> None: parser = argparse.ArgumentParser(description="Import a campaign JSON into the database and optionally validate/build it.") parser.add_argument("--campaign", required=True, help="Path to campaign.json") parser.add_argument("--api-key", default=settings.dev_bootstrap_api_key, help="API key used as the importing principal") parser.add_argument("--validate", action="store_true", help="Run semantic validation after import") parser.add_argument("--build", action="store_true", help="Build message jobs after import") parser.add_argument("--no-eml", action="store_true", help="Do not write generated .eml files during build") args = parser.parse_args() create_all_tables() campaign_path = Path(args.campaign).resolve() raw_json = json.loads(campaign_path.read_text(encoding="utf-8")) with SessionLocal() as session: api_key = authenticate_api_key(session, args.api_key) if not api_key: raise SystemExit("Invalid API key. Run init_db --with-dev-data first or pass --api-key.") user = session.get(User, api_key.user_id) campaign, version = create_campaign_version_from_json( session, tenant_id=api_key.tenant_id, user_id=user.id if user else None, raw_json=raw_json, source_filename=str(campaign_path), ) audit_event( session, tenant_id=api_key.tenant_id, user_id=api_key.user_id, api_key_id=api_key.id, action="campaign.imported", object_type="campaign", object_id=campaign.id, details={"version_id": version.id, "source_filename": str(campaign_path)}, commit=True, ) print(f"Campaign: {campaign.name} ({campaign.id})") print(f"Version: {version.version_number} ({version.id})") if args.validate: report = validate_campaign_version(session, tenant_id=api_key.tenant_id, version_id=version.id) audit_event(session, tenant_id=api_key.tenant_id, user_id=api_key.user_id, api_key_id=api_key.id, action="campaign.validated", object_type="campaign_version", object_id=version.id, details={"ok": report.get("ok")}, commit=True) print(f"Validation: ok={report['ok']}, errors={report['error_count']}, warnings={report['warning_count']}") if args.build: report = build_campaign_version(session, tenant_id=api_key.tenant_id, version_id=version.id, write_eml=not args.no_eml) audit_event(session, tenant_id=api_key.tenant_id, user_id=api_key.user_id, api_key_id=api_key.id, action="campaign.messages_built", object_type="campaign_version", object_id=version.id, details={"built_count": report.get("built_count"), "write_eml": not args.no_eml}, commit=True) print(f"Build: built={report['built_count']}, queueable={report['queueable_count']}, needs_review={report['needs_review_count']}") if __name__ == "__main__": main()