from __future__ import annotations import argparse from pathlib import Path from . import _io BUBBLE_STATUS = {"Active": "active", "Cancelled": "churned", "Paused": "paused"} def import_membership(export: dict, plan_id: str = "flat-899-eur-monthly") -> dict: members = [] for index, user in enumerate(export.get("users", []), start=1): bubble_id = user.get("bubble_id") or user.get("_id") or f"bubble-{index}" username = user.get("username") or user.get("email") or bubble_id status = BUBBLE_STATUS.get(user.get("status", "Active"), "active") members.append( { "id": f"member-{username}", "username": username, "external_id": bubble_id, "status": status, "joined_at": user.get("created") or user.get("joined_at"), "plan_id": user.get("plan") or plan_id, "source": "bubble", "churned_at": user.get("cancelled_at") if status == "churned" else None, } ) return { "version": 1, "snapshot_date": export.get("exported_at", export.get("snapshot_date")), "members": members, "note": "Imported from Bubble export", } def main(argv: list[str] | None = None) -> int: parser = argparse.ArgumentParser(description="Import Bubble membership export") parser.add_argument("--input", type=Path, required=True, help="Bubble JSON export") parser.add_argument( "--output", type=Path, default=Path(__file__).resolve().parent.parent.parent / "data" / "membership.json", ) parser.add_argument("--plan-id", default="flat-899-eur-monthly") args = parser.parse_args(argv) payload = import_membership(_io.read_export(args.input), args.plan_id) _io.write_registry(args.output, payload) print(f"Wrote {len(payload['members'])} members → {args.output}") return 0 if __name__ == "__main__": raise SystemExit(main())