Untitled
unknown
plain_text
9 months ago
7.8 kB
13
Indexable
# app/routers/leads.py
from fastapi import APIRouter, Depends, HTTPException, Query
from app.schemas.lead import LeadCreate, LeadUpdate, LeadOut
from app.core.deps import get_current_user, require_role
from app.db.mongodb import get_db
from datetime import datetime, timezone
from bson import ObjectId
router = APIRouter(prefix="/leads", tags=["Leads"])
# ---- HELPERS ----
def normalize_note(note: dict) -> dict:
return {
"id": str(note.get("_id")),
"author_id": str(note.get("author_id")),
"author_name": note.get("author_name", ""),
"content": note.get("content", ""),
"created_at": note.get("created_at"),
}
def normalize_lead(lead: dict) -> dict:
return {
"id": str(lead["_id"]),
"full_name": lead.get("full_name"),
"phone_e164": lead.get("phone_e164"),
"email": lead.get("email"),
"source": lead.get("source"),
"status": lead.get("status"),
"custom_status": lead.get("custom_status"),
"pool": lead.get("pool"),
"assigned_to": lead.get("assigned_to"), # e-posta veya None
"last_contact_at": lead.get("last_contact_at"),
"last_activity_at": lead.get("last_activity_at"),
"updated_at": lead.get("updated_at"),
"notes": [normalize_note(n) for n in lead.get("notes", [])],
}
async def resolve_assigned_email(lead: dict, db) -> dict:
"""assigned_to alanını id yerine email'e çevirir"""
if lead.get("assigned_to"):
try:
user = await db["users"].find_one({"_id": ObjectId(lead["assigned_to"])})
if user:
lead["assigned_to"] = user.get("email")
else:
lead["assigned_to"] = None
except Exception:
lead["assigned_to"] = None
else:
lead["assigned_to"] = None
return lead
# ---- ROUTES ----
# CREATE
@router.post("/", response_model=LeadOut)
async def create_lead(data: LeadCreate, user=Depends(require_role("admin"))):
db = get_db()
now = datetime.now(timezone.utc)
doc = {
"full_name": data.full_name,
"phone_e164": data.phone_e164,
"raw_phone": data.raw_phone,
"email": data.email,
"source": data.source,
"status": "Yeni",
"custom_status": None,
"pool": "Taze",
"assigned_to": None,
"last_contact_at": None,
"last_activity_at": None,
"last_update_at": now,
"notes": [],
"manager_notes": [],
"consultations": [],
"created_at": now,
"updated_at": now,
}
result = await db["leads"].insert_one(doc)
doc["_id"] = result.inserted_id
return normalize_lead(doc)
# LIST (dinamik filtreleme + pagination)
@router.get("/")
async def list_leads(
status: str | None = Query(None, description="Tekli ya da çoklu statü. Örn: cevapsız,meşgul,ulaşılamadı"),
pool: str | None = Query(None),
source: str | None = Query(None),
assigned_to: str | None = Query(None),
noteSearch: str | None = Query(None),
phone: str | None = Query(None),
page: int = Query(1, ge=1),
page_size: int = Query(500, ge=20, le=500),
user=Depends(get_current_user),
):
db = get_db()
query = {}
# 🔹 Sales sadece kendi leadlerini görsün
if not phone:
if user["role"] == "sales":
query["assigned_to"] = str(user["_id"])
# 🔹 Admin email filtresi
if assigned_to and user["role"] == "admin":
target_user = await db["users"].find_one({"email": assigned_to})
if target_user:
query["assigned_to"] = str(target_user["_id"])
else:
query["assigned_to"] = "__not_found__"
# 🔹 Status filtresi
if status:
statuses = [s.strip() for s in status.split(",") if s.strip()]
if len(statuses) > 1:
query["status"] = {"$in": statuses}
else:
query["status"] = {"$regex": f"^{statuses[0]}$", "$options": "i"}
# 🔹 Pool filtresi
if pool:
query["pool"] = {"$regex": f"^{pool}$", "$options": "i"}
if source:
query["source"] = {"$regex": source, "$options": "i"}
if phone:
query["phone_e164"] = phone
if noteSearch:
query["notes.content"] = {"$regex": noteSearch, "$options": "i"}
total = await db["leads"].count_documents(query)
skip = (page - 1) * page_size
leads = (
await db["leads"]
.find(query)
.skip(skip)
.limit(page_size)
.to_list(page_size)
)
# 🔹 Sales farklı lead ararsa dummy dön
if phone and user["role"] == "sales" and not leads:
lead = await db["leads"].find_one({"phone_e164": phone})
if lead and str(lead.get("assigned_to")) != str(user["_id"]):
lead = await resolve_assigned_email(lead, db)
return {
"total": 1,
"page": 1,
"page_size": 1,
"items": [{
"id": str(lead["_id"]),
"full_name": "Başka kullanıcıda",
"phone_e164": phone,
"email": None,
"source": None,
"status": None,
"custom_status": None,
"pool": None,
"assigned_to": lead.get("assigned_to"),
"last_contact_at": None,
"last_activity_at": None,
"updated_at": None,
"notes": [],
}]
}
result = []
for l in leads:
l = await resolve_assigned_email(l, db)
result.append(normalize_lead(l))
return {"total": total, "page": page, "page_size": page_size, "items": result}
# GET SINGLE LEAD
@router.get("/{lead_id}", response_model=LeadOut)
async def get_lead(lead_id: str, user=Depends(get_current_user)):
db = get_db()
lead = await db["leads"].find_one({"_id": ObjectId(lead_id)})
if not lead:
raise HTTPException(404, "Lead not found")
# 🔒 Sales sadece kendi lead'ini görebilsin
if user["role"] == "sales" and str(lead.get("assigned_to")) != str(user["_id"]):
raise HTTPException(403, "Permission denied")
# 🔹 assigned_to e-mail'e çevrilirken id kaybolmasın
assigned_to_id = lead.get("assigned_to")
lead = await resolve_assigned_email(lead, db)
if assigned_to_id:
lead["assigned_to_id"] = str(assigned_to_id)
# 🔹 notları normalize ederek dönelim
lead["notes"] = [normalize_note(n) for n in lead.get("notes", [])]
return normalize_lead(lead)
# UPDATE
@router.patch("/{lead_id}", response_model=LeadOut)
async def update_lead(lead_id: str, data: LeadUpdate, user=Depends(get_current_user)):
db = get_db()
lead = await db["leads"].find_one({"_id": ObjectId(lead_id)})
if not lead:
raise HTTPException(404, "Lead not found")
if user["role"] == "sales" and str(lead.get("assigned_to")) != str(user["_id"]):
raise HTTPException(403, "Permission denied")
update_data = {k: v for k, v in data.dict().items() if v is not None}
now = datetime.now(timezone.utc)
update_data["last_update_at"] = now
if "status" in update_data:
update_data["last_activity_at"] = now
await db["leads"].update_one({"_id": ObjectId(lead_id)}, {"$set": update_data})
new_lead = await db["leads"].find_one({"_id": ObjectId(lead_id)})
new_lead = await resolve_assigned_email(new_lead, db)
return normalize_lead(new_lead)
Editor is loading...
Leave a Comment