179 lines
7.4 KiB
Python
179 lines
7.4 KiB
Python
"""
|
|
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()
|