import json import os from typing import List, Optional from modules.projects.project import Project class ProjectHandler: def __init__(self, base_dir: str = None): # Par défaut, stocker sous Data/projects self.base_dir = base_dir or os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'Data', 'projects') os.makedirs(self.base_dir, exist_ok=True) def _client_dir(self, client_id: str) -> str: path = os.path.join(self.base_dir, client_id) os.makedirs(path, exist_ok=True) return path def _project_path(self, client_id: str, project_id: str) -> str: return os.path.join(self._client_dir(client_id), f"{project_id}.json") def list_projects(self, client_id: str) -> List[Project]: projects: List[Project] = [] directory = self._client_dir(client_id) if not os.path.isdir(directory): return projects for filename in os.listdir(directory): if filename.endswith('.json'): try: with open(os.path.join(directory, filename), 'r', encoding='utf-8') as f: data = json.load(f) projects.append(Project.from_dict(data)) except Exception: # Ignorer fichiers corrompus continue # Tri par date de mise à jour décroissante projects.sort(key=lambda p: p.updated_at or "", reverse=True) return projects def get_project(self, client_id: str, project_id: str) -> Optional[Project]: path = self._project_path(client_id, project_id) if not os.path.exists(path): return None with open(path, 'r', encoding='utf-8') as f: data = json.load(f) return Project.from_dict(data) def add_project(self, project: Project) -> str: path = self._project_path(project.client_id, project.id) with open(path, 'w', encoding='utf-8') as f: json.dump(project.to_dict(), f, ensure_ascii=False, indent=2) return project.id def update_project(self, project: Project) -> bool: path = self._project_path(project.client_id, project.id) if not os.path.exists(path): return False # mettre à jour updated_at from datetime import datetime project.updated_at = datetime.utcnow().isoformat() with open(path, 'w', encoding='utf-8') as f: json.dump(project.to_dict(), f, ensure_ascii=False, indent=2) return True def delete_project(self, client_id: str, project_id: str) -> bool: path = self._project_path(client_id, project_id) if os.path.exists(path): try: os.remove(path) return True except Exception: return False return False def add_task_for_project(self, project_id: str, title: str, due_date: str, description: str = "", priority: str = "normale", metadata: dict = None): """ Crée une tâche liée à un projet. :param project_id: ID du projet :param title: Titre de la tâche :param due_date: Date d'échéance au format ISO (YYYY-MM-DD) :param description: Description optionnelle :param priority: 'basse' | 'normale' | 'haute' :param metadata: métadonnées optionnelles :return: ID de la tâche créée """ from modules.tasks.task import Task from modules.tasks.task_handler import TaskHandler task = Task( title=title, due_date=due_date, description=description, entity_type="project", entity_id=project_id, priority=priority, metadata=metadata or {}, ) return TaskHandler().add_task(task)