""" One-time migration script: convert legacy negotiating/has_problem flags to new structure. Run AFTER deploying the new backend code: cd backend && python migrate_customer_flags.py What it does: 1. For each customer with negotiating=True: - Creates an order subcollection document with status="negotiating" - Sets relationship_status="active" (only if currently "lead" or "prospect") 2. For each customer with has_problem=True: - Appends one entry to technical_issues with active=True 3. Removes negotiating and has_problem fields from every customer document 4. Initialises relationship_status="lead" on any customer missing it 5. Recomputes crm_summary for each affected customer """ import sys import os import uuid from datetime import datetime # Make sure we can import backend modules sys.path.insert(0, os.path.dirname(__file__)) from shared.firebase import init_firebase, get_db init_firebase() def migrate(): db = get_db() customers_ref = db.collection("crm_customers") docs = list(customers_ref.stream()) print(f"Found {len(docs)} customer documents.") migrated_neg = 0 migrated_prob = 0 now = datetime.utcnow().isoformat() for doc in docs: data = doc.to_dict() or {} customer_id = doc.id updates = {} changed = False # ── 1. Initialise new fields if missing ────────────────────────────── if "relationship_status" not in data: updates["relationship_status"] = "lead" changed = True if "technical_issues" not in data: updates["technical_issues"] = [] changed = True if "install_support" not in data: updates["install_support"] = [] changed = True if "transaction_history" not in data: updates["transaction_history"] = [] changed = True # ── 2. Migrate negotiating flag ─────────────────────────────────────── if data.get("negotiating"): order_id = str(uuid.uuid4()) order_data = { "customer_id": customer_id, "order_number": f"ORD-{datetime.utcnow().year}-001-migrated", "title": "Migrated from legacy negotiating flag", "created_by": "system", "status": "negotiating", "status_updated_date": now, "status_updated_by": "system", "items": [], "subtotal": 0, "discount": None, "total_price": 0, "currency": "EUR", "shipping": None, "payment_status": { "required_amount": 0, "received_amount": 0, "balance_due": 0, "advance_required": False, "advance_amount": None, "payment_complete": False, }, "invoice_path": None, "notes": "Migrated from legacy negotiating flag", "timeline": [{ "date": now, "type": "note", "note": "Migrated from legacy negotiating flag", "updated_by": "system", }], "created_at": now, "updated_at": now, } customers_ref.document(customer_id).collection("orders").document(order_id).set(order_data) current_rel = updates.get("relationship_status") or data.get("relationship_status", "lead") if current_rel in ("lead", "prospect"): updates["relationship_status"] = "active" migrated_neg += 1 print(f" [{customer_id}] Created negotiating order, set relationship_status=active") # ── 3. Migrate has_problem flag ─────────────────────────────────────── if data.get("has_problem"): existing_issues = list(updates.get("technical_issues") or data.get("technical_issues") or []) existing_issues.append({ "active": True, "opened_date": data.get("updated_at") or now, "resolved_date": None, "note": "Migrated from legacy has_problem flag", "opened_by": "system", "resolved_by": None, }) updates["technical_issues"] = existing_issues migrated_prob += 1 changed = True print(f" [{customer_id}] Appended technical issue from has_problem flag") # ── 4. Remove legacy fields ─────────────────────────────────────────── from google.cloud.firestore_v1 import DELETE_FIELD if "negotiating" in data: updates["negotiating"] = DELETE_FIELD changed = True if "has_problem" in data: updates["has_problem"] = DELETE_FIELD changed = True if changed or data.get("negotiating") or data.get("has_problem"): updates["updated_at"] = now customers_ref.document(customer_id).update(updates) # ── 5. Recompute crm_summary ────────────────────────────────────────── # Re-read updated doc to compute summary updated_doc = customers_ref.document(customer_id).get() updated_data = updated_doc.to_dict() or {} issues = updated_data.get("technical_issues") or [] active_issues = [i for i in issues if i.get("active")] support = updated_data.get("install_support") or [] active_support = [s for s in support if s.get("active")] TERMINAL = {"declined", "complete"} active_order_status = None active_order_status_date = None active_order_title = None latest_date = "" for odoc in customers_ref.document(customer_id).collection("orders").stream(): odata = odoc.to_dict() or {} if odata.get("status") not in TERMINAL: upd = odata.get("status_updated_date") or odata.get("created_at") or "" if upd > latest_date: latest_date = upd active_order_status = odata.get("status") active_order_status_date = upd active_order_title = odata.get("title") summary = { "active_order_status": active_order_status, "active_order_status_date": active_order_status_date, "active_order_title": active_order_title, "active_issues_count": len(active_issues), "latest_issue_date": max((i.get("opened_date") or "") for i in active_issues) if active_issues else None, "active_support_count": len(active_support), "latest_support_date": max((s.get("opened_date") or "") for s in active_support) if active_support else None, } customers_ref.document(customer_id).update({"crm_summary": summary}) print(f"\nMigration complete.") print(f" Negotiating orders created: {migrated_neg}") print(f" Technical issues created: {migrated_prob}") print(f" Total customers processed: {len(docs)}") if __name__ == "__main__": migrate()