feat: LeadHunter CRUD API + auth fixes + blueprint registrations (HRT-136)
- leadhunter_crm.py: add update_lead(), delete_lead(); expand VALID_STATUSES to 7-step Kanban with legacy migration map - leadhunter_api.py: add GET/PUT/DELETE /api/leads/<id> endpoints; import update_lead, delete_lead - portal_server.py: add routes for /leadhunter/clients/le-big-ben/ and /formation/ai102 - saas_api_v1.py: register user blueprint (HRT-79/80) and history blueprint (HRT-81) - api_v1/routes/user.py: switch auth import to saas_auth.require_auth - api_v1/routes/history.py: fix auth import + request.current_user fallback - api_v1/routes/ml_feedback.py: fix auth import + request.current_user fallback Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -52,8 +52,24 @@ if not logger.handlers:
|
||||
# ─── Chemin DB ───────────────────────────────────────────────────────────────
|
||||
DB_PATH = "/home/h3r7/leadhunter.db"
|
||||
|
||||
# Statuts valides pour un lead
|
||||
VALID_STATUSES = {"new", "contacted", "closed", "rejected"}
|
||||
# Statuts valides pour un lead (7 etapes Kanban)
|
||||
VALID_STATUSES = {
|
||||
"nouveau", # NOUVEAU
|
||||
"contacte", # CONTACTÉ
|
||||
"interesse", # INTÉRESSÉ
|
||||
"demo_planifiee", # DÉMO PLANIFIÉE
|
||||
"proposition_envoyee", # PROPOSITION ENVOYÉE
|
||||
"negotiation", # NÉGOCIATION
|
||||
"signe_ou_refuse", # SIGNÉ / REFUSÉ
|
||||
}
|
||||
|
||||
# Mapping des anciens statuts vers les nouveaux (pour migration)
|
||||
LEGACY_STATUS_MAP = {
|
||||
"new": "nouveau",
|
||||
"contacted": "contacte",
|
||||
"closed": "signe_ou_refuse",
|
||||
"rejected": "signe_ou_refuse",
|
||||
}
|
||||
|
||||
|
||||
# ─── Initialisation ──────────────────────────────────────────────────────────
|
||||
@@ -212,6 +228,77 @@ def get_lead_by_id(lead_id: int, db_path: str = DB_PATH) -> Optional[dict]:
|
||||
return None
|
||||
|
||||
|
||||
def update_lead(lead_id: int, data: dict, db_path: str = DB_PATH) -> bool:
|
||||
"""
|
||||
Met à jour un lead avec les champs fournis.
|
||||
|
||||
Args:
|
||||
lead_id: id du lead.
|
||||
data: dict avec les champs a mettre a jour (name, address, phone, etc.)
|
||||
|
||||
Returns:
|
||||
True si mise a jour reussie, False sinon.
|
||||
"""
|
||||
allowed_fields = {
|
||||
"name",
|
||||
"address",
|
||||
"phone",
|
||||
"rating",
|
||||
"reviews_count",
|
||||
"website",
|
||||
"score",
|
||||
"rgpd_ok",
|
||||
"status",
|
||||
}
|
||||
fields_to_update = {k: v for k, v in data.items() if k in allowed_fields}
|
||||
|
||||
if not fields_to_update:
|
||||
logger.warning(
|
||||
f"update_lead : aucun champ valide fourni pour lead_id={lead_id}"
|
||||
)
|
||||
return False
|
||||
|
||||
if (
|
||||
"status" in fields_to_update
|
||||
and fields_to_update["status"] not in VALID_STATUSES
|
||||
):
|
||||
logger.warning(f"update_lead : statut invalide '{fields_to_update['status']}'")
|
||||
return False
|
||||
|
||||
try:
|
||||
with _get_conn(db_path) as conn:
|
||||
set_clause = ", ".join([f"{k} = ?" for k in fields_to_update])
|
||||
values = list(fields_to_update.values()) + [lead_id]
|
||||
conn.execute(f"UPDATE leads SET {set_clause} WHERE id = ?", values)
|
||||
logger.info(
|
||||
f"Lead id={lead_id} mis a jour : {list(fields_to_update.keys())}"
|
||||
)
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.warning(f"update_lead error : {e}")
|
||||
return False
|
||||
|
||||
|
||||
def delete_lead(lead_id: int, db_path: str = DB_PATH) -> bool:
|
||||
"""
|
||||
Supprime un lead physiquement.
|
||||
|
||||
Args:
|
||||
lead_id: id du lead a supprimer.
|
||||
|
||||
Returns:
|
||||
True si suppression reussie, False sinon.
|
||||
"""
|
||||
try:
|
||||
with _get_conn(db_path) as conn:
|
||||
conn.execute("DELETE FROM leads WHERE id = ?", (lead_id,))
|
||||
logger.info(f"Lead id={lead_id} supprime")
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.warning(f"delete_lead error : {e}")
|
||||
return False
|
||||
|
||||
|
||||
def update_lead_status(lead_id: int, status: str, db_path: str = DB_PATH) -> bool:
|
||||
"""
|
||||
Met à jour le statut d'un lead.
|
||||
|
||||
Reference in New Issue
Block a user