diff --git a/__pycache__/menu_handlers.cpython-312.pyc b/__pycache__/menu_handlers.cpython-312.pyc index c4a3838..dad4e16 100644 Binary files a/__pycache__/menu_handlers.cpython-312.pyc and b/__pycache__/menu_handlers.cpython-312.pyc differ diff --git a/__pycache__/menu_principal.cpython-312.pyc b/__pycache__/menu_principal.cpython-312.pyc index 3d9d557..9e0330b 100644 Binary files a/__pycache__/menu_principal.cpython-312.pyc and b/__pycache__/menu_principal.cpython-312.pyc differ diff --git a/__pycache__/ticket_manager.cpython-312.pyc b/__pycache__/ticket_manager.cpython-312.pyc index a9123ee..9ada2db 100644 Binary files a/__pycache__/ticket_manager.cpython-312.pyc and b/__pycache__/ticket_manager.cpython-312.pyc differ diff --git a/menu_handlers.py b/menu_handlers.py index 99ce47d..cc712c3 100644 --- a/menu_handlers.py +++ b/menu_handlers.py @@ -1,9 +1,40 @@ from ticket_manager import TicketManager -from utils import get_user_choice +from utils import get_user_choice, print_error # Initialisation de l'objet ticket_manager = TicketManager() +def handle_search_ticket_by_id(): + """Gère la recherche d'un ticket par ID""" + ticket_id = input("Entrez l'ID du ticket(ou 'q' pour quitter): ") + if ticket_id_input.lower() == 'q': + return + try: + ticket_id = int(ticket_id_input) + except ValueError: + print_error("L'ID du ticket doit être un n ombre entier.") + return + + ticket = ticket_manager.get_ticket_by_id(ticket_id) + if ticket: + print("\n Ticket trouvé:") + print(ticket) + else: + print_error(f"Aucun ticket trouvé avec l'ID: {ticket_id}") + +def handle_search_ticket_by_code(): + """Recherche un ticket via son code""" + ticket_code = input("\nEntrez le code du ticket à rechercher (ou 'q' pour quitter): ") + if ticket_code.lower() == 'q': + return + + ticket = ticket_manager.get_ticket_by_code(ticket_code) + if ticket: + print("\n Ticket trouvé:") + print(ticket) + else: + print_error(f"Aucun ticket trouvé avec le code '{ticket_code}'.") + def handle_project_tickets_by_stage(): """Gère l'exportation des tickets d'un projet par étape""" # Récupérer la liste des projets disponibles @@ -11,7 +42,7 @@ def handle_project_tickets_by_stage(): if not projects: print("Aucun projet disponible. Impossible de continuer.") return - + # Demander à l'utilisateur de choisir un projet project_id_input = input("\nEntrez l'ID du projet (ou 'q' pour quitter): ") if project_id_input.lower() == 'q': @@ -19,85 +50,12 @@ def handle_project_tickets_by_stage(): try: project_id = int(project_id_input) - if project_id not in projects: - print(f"Aucun projet trouvé avec l'ID: {project_id}") + if project_id not in projects.keys(): + print_error(f"Aucun projet trouvé avec l'ID: {project_id}") return except ValueError: print("L'ID du projet doit être un nombre entier.") return - # Récupérer les étapes (stage_id) du projet - print(f"\nRécupération des étapes du projet: {projects[project_id]} (ID: {project_id})") - stages = ticket_manager.get_project_stages(project_id) - - if not stages: - print("Aucune étape trouvée pour ce projet. Impossible de continuer.") - return - - # Afficher les étapes disponibles - print("\nÉtapes disponibles:") - for stage_id, stage_name in stages.items(): - print(f"ID: {stage_id} - {stage_name}") - - # Demander à l'utilisateur s'il veut sélectionner ou exclure des étapes - selection_mode = input("\nSouhaitez-vous:\n1. Exporter toutes les étapes\n2. Sélectionner des étapes spécifiques par ID\n3. Exclure certaines étapes par ID\nVotre choix (1/2/3): ") - - selected_stage_ids = None - - if selection_mode == '2': - # Sélectionner des étapes spécifiques par ID - stage_id_input = input("Entrez les IDs des étapes à inclure (séparés par des virgules): ") - try: - selected_stage_ids = [int(x.strip()) for x in stage_id_input.split(',') if x.strip()] - # Vérifier que les IDs existent dans les étapes disponibles - valid_ids = [stage_id for stage_id in selected_stage_ids if stage_id in stages] - invalid_ids = [stage_id for stage_id in selected_stage_ids if stage_id not in stages] - - selected_stage_ids = valid_ids - - if invalid_ids: - print(f"Attention: Les IDs suivants ne sont pas valides et seront ignorés: {', '.join(map(str, invalid_ids))}") - - if not selected_stage_ids: - print("Aucun ID d'étape valide sélectionné. Exportation annulée.") - return - - print(f"Étapes sélectionnées: {', '.join([f'{stages[stage_id]} (ID: {stage_id})' for stage_id in selected_stage_ids])}") - except ValueError: - print("Erreur dans la sélection des étapes. Format attendu: 1,2,3,...") - return - - elif selection_mode == '3': - # Exclure certaines étapes par ID - stage_id_input = input("Entrez les IDs des étapes à exclure (séparés par des virgules): ") - try: - excluded_stage_ids = [int(x.strip()) for x in stage_id_input.split(',') if x.strip()] - # Vérifier que les IDs existent dans les étapes disponibles - valid_excluded_ids = [stage_id for stage_id in excluded_stage_ids if stage_id in stages] - invalid_ids = [stage_id for stage_id in excluded_stage_ids if stage_id not in stages] - - excluded_stage_ids = valid_excluded_ids - - if invalid_ids: - print(f"Attention: Les IDs suivants ne sont pas valides et seront ignorés: {', '.join(map(str, invalid_ids))}") - - # Sélectionner toutes les étapes sauf les exclues - selected_stage_ids = [stage_id for stage_id in stages.keys() if stage_id not in excluded_stage_ids] - - if not selected_stage_ids: - print("Toutes les étapes ont été exclues. Exportation annulée.") - return - - print(f"Étapes sélectionnées: {', '.join([f'{stages[stage_id]} (ID: {stage_id})' for stage_id in selected_stage_ids])}") - except ValueError: - print("Erreur dans la sélection des étapes. Format attendu: 1,2,3,...") - return - - # Confirmer l'action - confirmation = input(f"\nVoulez-vous exporter les tickets du projet {projects[project_id]}? (o/n): ") - if confirmation.lower() != 'o': - print("Exportation annulée.") - return - - # Exporter les tickets - ticket_manager.export_tickets_by_project_and_stage(project_id, selected_stage_ids) \ No newline at end of file + #Exportet les tickets du projet + ticket_manager.export_tickets_by_project_and_stage(project_id) \ No newline at end of file diff --git a/ticket_manager.py b/ticket_manager.py index e264c5c..ef11efc 100644 --- a/ticket_manager.py +++ b/ticket_manager.py @@ -1,6 +1,5 @@ from odoo_connection import OdooConnection import os -import json from utils import save_json, ensure_export_directory, print_error from config import EXPORT_DIR from data_filter import filter_ticket_data @@ -43,13 +42,8 @@ class TicketManager: def get_ticket_by_id(self, ticket_id): """ Récupère les détails d'un ticket par son ID et applique le filtre """ - fields_to_read = ['id', 'name', 'code', 'stage_id', 'date_deadline', 'description', 'message_ids'] - - # Vérifier la connexion avant d'exécuter la requête - if not self._ensure_connection(): - print_error("Connexion Odoo indisponible.") - return None - + fields_to_read = ['id', 'name', 'code', 'stage_id', 'project_id', 'date_deadline', 'description', 'message_ids'] + # Récupérer les données du ticket ticket_data = self._safe_execute(self.model_name, 'read', [ticket_id], fields_to_read) @@ -59,64 +53,64 @@ class TicketManager: # Nettoyer et filtrer les données du ticket return filter_ticket_data(ticket_data[0]) # Utilisation de data_filter.py + + def get_ticket_by_code(self, ticket_code): + """Récupérer un ticket via son code""" + domain = [('code', '=', ticket_code)] + ticket_ids = self._safe_execute(self.model_name, 'search', domain, 0, 1) + if not ticket_ids: + print_error(f"Aucun ticket trouvé avec le code '{ticket_code}'.") + return None + + return self.get_ticket_by_id(ticket_ids[0]) + + def get_available_projects(self): + """Retourne la liste des projets disponibles""" + projects = self._safe_execute('project.project', 'search_read', [], ['id', 'name']) + if not projects: + print_error("Aucun projet trouvé.") + return {} + return {proj['id']: proj['name'] for proj in projects} - def export_tickets_by_project_and_stage(self, project_id, selected_stage_ids=None): + def export_tickets_by_project_and_stage(self, project_id): """ Exporte les tickets d'un projet classés par étape """ # Vérifier la connexion Odoo if not self._ensure_connection(): print_error("Connexion Odoo indisponible.") return - - # Récupérer le projet depuis Odoo - project_data = self._safe_execute('project.project', 'search_read', [('id', '=', project_id)], ['id', 'name']) - if not project_data: - print_error(f"Projet ID {project_id} introuvable.") - return - - project_name = project_data[0]['name'] - - # Construire le domaine de recherche des tickets - domain = [('project_id', '=', project_id)] - if selected_stage_ids: - domain.append(('stage_id', 'in', selected_stage_ids)) - + # Récupérer les tickets du projet + domain = [('project_id', '=', project_id)] ticket_ids = self._safe_execute(self.model_name, 'search', domain, 0, 1000) if not ticket_ids: - print_error("Aucun ticket trouvé pour ce projet.") + print_error(f"Aucun ticket trouvé pour le projet {project_id}.") return - + # Lire les détails des tickets - tickets = [self.get_ticket_by_id(ticket_id) for ticket_id in ticket_ids if self.get_ticket_by_id(ticket_id)] - - # Trier les tickets par étape + tickets = [] + for ticket_id in ticket_ids: + ticket = self.get_ticket_by_id(ticket_id) + if ticket: + tickets.append(ticket) + + #trier les tickets par étape tickets_by_stage = {} for ticket in tickets: - #Vérifier que ticket est bien un dictionnaire - if not isinstance(ticket, dict): - print_error("Erreur: le format du ticket est invalide.") - return None - # Vérifier que "Champs Relationnels" existe champs_relationnels = ticket.get("Champs Relationnels", {}) - - # Vérifier que "stage_id" existe et est une liste avec au moins 2 éléments stage_data = champs_relationnels.get("stage_id", [0, "Non classé"]) stage_id = stage_data[0] if isinstance(stage_data, list) and len(stage_data) > 0 else 0 stage_name = stage_data[1] if isinstance(stage_data, list) and len(stage_data) > 1 else "Non classé" - + key = f"{stage_id}_{stage_name}" - if key not in tickets_by_stage: - tickets_by_stage[key] = [] - tickets_by_stage[key].append(ticket) - - # Créer le répertoire du projet - project_dir = ensure_export_directory(f"project_{project_id}_{project_name.replace(' ', '_')}") - - # Sauvegarder les tickets par étape + tickets_by_stage.setdefault(key, []).append(ticket) + + # Sauvegarde des fichiers + project_dir = ensure_export_directory(f"project_{project_id}") for stage_key, stage_tickets in tickets_by_stage.items(): stage_dir = os.path.join(project_dir, stage_key) os.makedirs(stage_dir, exist_ok=True) save_json(os.path.join(stage_dir, "all_tickets.json"), stage_tickets) - + print(f"Exportation terminée. Les fichiers sont enregistrés dans : {project_dir}/") +