first commit

This commit is contained in:
mrtoine 2025-09-20 13:18:04 +02:00
commit e6c52820cd
227 changed files with 16156 additions and 0 deletions

100
jobs/daily_reminder_job.py Normal file
View file

@ -0,0 +1,100 @@
"""
Job quotidien: détecte les tâches 'du jour' liées aux prospects
et génère des brouillons d'emails basés sur un template.
À exécuter via crontab, par exemple:
0 8 * * * /usr/bin/python3 /chemin/vers/le/projet/jobs/daily_reminder_job.py >> /var/log/reminder_job.log 2>&1
"""
from datetime import date
import sys
import os
# S'assurer que le projet est dans le PYTHONPATH quand lancé via cron
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if BASE_DIR not in sys.path:
sys.path.insert(0, BASE_DIR)
from modules.tasks.task_handler import TaskHandler
from modules.crm.prospect_handler import ProspectHandler
from modules.email.email_manager import EmailTemplate
from modules.email.draft import EmailDraft
from modules.email.draft_handler import DraftHandler
DEFAULT_TEMPLATE_ID = "prospect_followup"
def _render_with_fallback(template_mgr: EmailTemplate, template_id: str, context: dict) -> dict:
"""
Rend un template via EmailTemplate. Si introuvable, fabrique un contenu par défaut.
Retourne dict {subject, content}
"""
rendered = template_mgr.render_template(template_id, context=context)
if rendered:
return rendered
# Fallback basique
subject = f"Relance {context.get('name') or ''}".strip()
content = (
f"<p>Bonjour {context.get('name','')},</p>"
f"<p>Je me permets de revenir vers vous au sujet de {context.get('company','votre société')}."
f"</p><p>Restant à votre disposition,</p>"
)
return {"subject": subject, "content": content}
def main():
today = date.today().isoformat()
tasks = TaskHandler().list_today_tasks(status="todo")
# Filtrer uniquement les tâches liées aux prospects (interprétées comme 'rappel')
prospect_tasks = [t for t in tasks if t.entity_type == "prospect"]
if not prospect_tasks:
return 0
prospect_handler = ProspectHandler()
template_mgr = EmailTemplate()
draft_handler = DraftHandler()
created = 0
for t in prospect_tasks:
# Évite doublons: un draft existe déjà pour cette tâche ?
if draft_handler.find_existing_for_task(t.id):
continue
# Récupère prospect pour variables
prospect = prospect_handler.get_prospect_by_id(t.entity_id) if t.entity_id else None
if not prospect:
continue
to_email = prospect.email or ""
if not to_email:
# pas de destinataire, aucun draft créé
continue
context = {
"name": prospect.name,
"company": prospect.company or "",
}
rendered = _render_with_fallback(template_mgr, DEFAULT_TEMPLATE_ID, context)
draft = EmailDraft(
prospect_id=prospect.id,
to_email=to_email,
subject=rendered["subject"],
content=rendered["content"],
status="draft",
template_id=DEFAULT_TEMPLATE_ID,
task_id=t.id,
metadata={
"generated_for_date": today,
"task_title": t.title,
},
)
draft_handler.add_draft(draft)
created += 1
return created
if __name__ == "__main__":
sys.exit(main())