SuiteConsultance/modules/email/draft_handler.py
2025-09-20 13:18:04 +02:00

89 lines
3.3 KiB
Python

import os
import json
from typing import List, Optional, Dict, Any
from datetime import datetime
from modules.email.draft import EmailDraft
class DraftHandler:
"""
Gestionnaire de brouillons (fichiers JSON).
Répertoire: Data/email_drafts
"""
def __init__(self, base_dir: Optional[str] = None):
base_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
self.base_dir = base_dir or os.path.join(base_root, "Data", "email_drafts")
os.makedirs(self.base_dir, exist_ok=True)
def _draft_path(self, draft_id: str) -> str:
return os.path.join(self.base_dir, f"{draft_id}.json")
def add_draft(self, draft: EmailDraft) -> str:
path = self._draft_path(draft.id)
with open(path, "w", encoding="utf-8") as f:
json.dump(draft.to_dict(), f, ensure_ascii=False, indent=2)
return draft.id
def get_draft(self, draft_id: str) -> Optional[EmailDraft]:
path = self._draft_path(draft_id)
if not os.path.exists(path):
return None
with open(path, "r", encoding="utf-8") as f:
return EmailDraft.from_dict(json.load(f))
def update_draft(self, draft: EmailDraft) -> bool:
path = self._draft_path(draft.id)
if not os.path.exists(path):
return False
with open(path, "w", encoding="utf-8") as f:
json.dump(draft.to_dict(), f, ensure_ascii=False, indent=2)
return True
def delete_draft(self, draft_id: str) -> bool:
path = self._draft_path(draft_id)
if os.path.exists(path):
try:
os.remove(path)
return True
except Exception:
return False
return False
def list_drafts(self, status: Optional[str] = None) -> List[EmailDraft]:
drafts: List[EmailDraft] = []
for filename in os.listdir(self.base_dir):
if filename.endswith(".json"):
try:
with open(os.path.join(self.base_dir, filename), "r", encoding="utf-8") as f:
data = json.load(f)
d = EmailDraft.from_dict(data)
if status is None or d.status == status:
drafts.append(d)
except Exception:
continue
# Tri: plus récents d'abord
drafts.sort(key=lambda d: d.created_at or "", reverse=True)
return drafts
def list_pending(self) -> List[EmailDraft]:
return self.list_drafts(status="draft")
def mark_sent(self, draft_id: str, success: bool, error_message: Optional[str] = None) -> bool:
d = self.get_draft(draft_id)
if not d:
return False
d.status = "sent" if success else "failed"
d.sent_at = datetime.utcnow().isoformat()
d.error_message = None if success else (error_message or "Unknown error")
return self.update_draft(d)
def find_existing_for_task(self, task_id: str) -> Optional[EmailDraft]:
"""
Évite les doublons: si un draft 'draft' existe déjà pour cette tâche, le renvoie.
Les brouillons 'failed' ne bloquent pas la régénération.
"""
for d in self.list_drafts():
if d.task_id == task_id and d.status == "draft":
return d
return None