mirror of
https://github.com/Ladebeze66/projetcbaollm.git
synced 2025-12-15 20:06:53 +01:00
version4
This commit is contained in:
parent
7e8bfc3a07
commit
6f58ca7ca3
@ -71,10 +71,10 @@ def chat_interface(user, user_input):
|
|||||||
# Affichage des derniers messages sous forme de bulle de chat
|
# Affichage des derniers messages sous forme de bulle de chat
|
||||||
history_display = ""
|
history_display = ""
|
||||||
for c in user_history[-5:]:
|
for c in user_history[-5:]:
|
||||||
history_display += f"👤 **{user}** : {c['user']}\n"
|
history_display += f"Utilisateur : {c['user']}\n"
|
||||||
history_display += f"🤖 **Bot** : {c['bot']}\n\n"
|
history_display += f"Bot : {c['bot']}\n\n"
|
||||||
|
|
||||||
return f"📌 **Utilisateur :** {user}\n\n{history_display}👤 **{user}** : {user_input}\n🤖 **Bot** : {response}"
|
return f"Utilisateur : {user}\n\n{history_display}Utilisateur : {user_input}\nBot : {response}"
|
||||||
|
|
||||||
# Interface Gradio stylisée
|
# Interface Gradio stylisée
|
||||||
with gr.Blocks(css="""
|
with gr.Blocks(css="""
|
||||||
@ -85,7 +85,7 @@ with gr.Blocks(css="""
|
|||||||
.gr-button {background-color: #007bff; color: white; border-radius: 5px;}
|
.gr-button {background-color: #007bff; color: white; border-radius: 5px;}
|
||||||
""") as iface:
|
""") as iface:
|
||||||
with gr.Column():
|
with gr.Column():
|
||||||
gr.Markdown("<h2 style='text-align: center;'>💬 Chat avec Ollama OVH</h2>")
|
gr.Markdown("<h2 style='text-align: center;'>Chat avec Ollama OVH</h2>")
|
||||||
|
|
||||||
with gr.Row():
|
with gr.Row():
|
||||||
user_input = gr.Textbox(label="Nom d'utilisateur", placeholder="Entrez votre nom...", interactive=True)
|
user_input = gr.Textbox(label="Nom d'utilisateur", placeholder="Entrez votre nom...", interactive=True)
|
||||||
|
|||||||
@ -1,16 +1,6 @@
|
|||||||
from menu_principal import run_menu
|
from menu_principal import run_menu
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Point d'entrée principal de l'application"""
|
|
||||||
print("=================================================")
|
|
||||||
print(" GESTIONNAIRE DE TICKETS ODOO SIMPLIFIÉ ")
|
|
||||||
print("=================================================")
|
|
||||||
print("Fonctionnalités:")
|
|
||||||
print("1. Afficher la liste des modèles disponibles")
|
|
||||||
print("2. Afficher les champs d'un modèle donné")
|
|
||||||
print("3. Exporter les informations des champs en JSON")
|
|
||||||
print("4. Exporter les tickets d'un projet par étape")
|
|
||||||
print("=================================================")
|
|
||||||
|
|
||||||
run_menu()
|
run_menu()
|
||||||
|
|
||||||
|
|||||||
@ -15,32 +15,24 @@ class TicketManager:
|
|||||||
self.model_name = "project.task"
|
self.model_name = "project.task"
|
||||||
|
|
||||||
def _check_connection(self):
|
def _check_connection(self):
|
||||||
"""Vérifie que la connexion Odoo est active"""
|
"""Vérifie la connexion Odoo"""
|
||||||
if self.odoo is None:
|
if self.odoo is None:
|
||||||
print("Erreur: La connexion à Odoo n'est pas établie.")
|
|
||||||
print("Tentative de reconnexion...")
|
|
||||||
try:
|
try:
|
||||||
self.conn = OdooConnection()
|
self.conn = OdooConnection()
|
||||||
self.odoo = self.conn.get_odoo_instance()
|
self.odoo = self.conn.get_odoo_instance()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Erreur lors de la tentative de reconnexion: {e}")
|
print(f"Erreur de connexion: {e}")
|
||||||
self.odoo = None
|
self.odoo = None
|
||||||
|
|
||||||
return self.odoo is not None
|
return self.odoo is not None
|
||||||
|
|
||||||
def _safe_execute(self, model, method, *args):
|
def _safe_execute(self, model, method, *args):
|
||||||
"""Exécute une méthode Odoo de manière sécurisée"""
|
"""Exécute une méthode Odoo de manière sécurisée"""
|
||||||
if not self._check_connection():
|
if not self._check_connection():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if self.odoo is None:
|
|
||||||
print("Erreur: Impossible d'exécuter la commande, la connexion à Odoo est inactive.")
|
|
||||||
return None
|
|
||||||
|
|
||||||
return self.odoo.execute(model, method, *args)
|
return self.odoo.execute(model, method, *args)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Erreur lors de l'exécution de {method} sur {model}: {e}")
|
print(f"Erreur lors de {method} sur {model}: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def list_models(self):
|
def list_models(self):
|
||||||
@ -54,7 +46,7 @@ class TicketManager:
|
|||||||
for model in models:
|
for model in models:
|
||||||
print(f"Modèle: {model['name']} (ID: {model['model']})")
|
print(f"Modèle: {model['name']} (ID: {model['model']})")
|
||||||
return models
|
return models
|
||||||
|
|
||||||
def list_model_fields(self, model_name):
|
def list_model_fields(self, model_name):
|
||||||
"""Affiche les champs d'un modèle donné"""
|
"""Affiche les champs d'un modèle donné"""
|
||||||
fields_info = self._safe_execute(model_name, 'fields_get')
|
fields_info = self._safe_execute(model_name, 'fields_get')
|
||||||
@ -66,285 +58,7 @@ class TicketManager:
|
|||||||
for field_name, field_data in fields_info.items():
|
for field_name, field_data in fields_info.items():
|
||||||
print(f"Champ: {field_name} - Type: {field_data['type']}")
|
print(f"Champ: {field_name} - Type: {field_data['type']}")
|
||||||
return fields_info
|
return fields_info
|
||||||
|
|
||||||
def export_model_fields_to_json(self, model_name, filename):
|
|
||||||
"""Exporte les informations des champs d'un modèle en JSON"""
|
|
||||||
fields_info = self.list_model_fields(model_name)
|
|
||||||
if not fields_info:
|
|
||||||
return False
|
|
||||||
|
|
||||||
file_path = os.path.join(EXPORT_DIR, f"{filename}.json")
|
|
||||||
try:
|
|
||||||
with open(file_path, 'w', encoding='utf-8') as f:
|
|
||||||
json.dump(fields_info, f, indent=4, ensure_ascii=False)
|
|
||||||
print(f"Informations des champs exportées dans {file_path}")
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Erreur lors de l'exportation des champs: {str(e)}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_ticket_by_id(self, ticket_id):
|
|
||||||
"""Récupère un ticket par son ID"""
|
|
||||||
all_fields = self._safe_execute(self.model_name, 'fields_get')
|
|
||||||
if not all_fields:
|
|
||||||
return None
|
|
||||||
|
|
||||||
field_names = list(all_fields.keys())
|
|
||||||
|
|
||||||
ticket_data = self._safe_execute(self.model_name, 'read', [ticket_id], field_names)
|
|
||||||
if not ticket_data:
|
|
||||||
return None
|
|
||||||
|
|
||||||
ticket = ticket_data[0]
|
|
||||||
formatted_ticket = {
|
|
||||||
"ID du Ticket": ticket["id"],
|
|
||||||
"Nom": ticket["name"],
|
|
||||||
"Code": ticket.get("code", "N/A"),
|
|
||||||
"Date Limite": ticket.get("date_deadline", "Non défini"),
|
|
||||||
"Champs Simples": {},
|
|
||||||
"Champs Relationnels": {},
|
|
||||||
"Discussions": []
|
|
||||||
}
|
|
||||||
|
|
||||||
# Classer les champs par type
|
|
||||||
for field_name, field_info in all_fields.items():
|
|
||||||
field_type = field_info.get('type')
|
|
||||||
if field_type in ["many2one", "one2many", "many2many"]:
|
|
||||||
if field_name in ticket:
|
|
||||||
formatted_ticket["Champs Relationnels"][field_name] = ticket[field_name]
|
|
||||||
else:
|
|
||||||
if field_name in ticket:
|
|
||||||
formatted_ticket["Champs Simples"][field_name] = ticket[field_name]
|
|
||||||
|
|
||||||
# Récupérer les discussions
|
|
||||||
if "message_ids" in ticket and ticket["message_ids"]:
|
|
||||||
formatted_ticket["Discussions"] = self.get_ticket_discussions(ticket["message_ids"])
|
|
||||||
|
|
||||||
return formatted_ticket
|
|
||||||
|
|
||||||
def get_ticket_discussions(self, message_ids):
|
|
||||||
"""Récupère et nettoie les discussions associées à un ticket"""
|
|
||||||
model_name = "mail.message"
|
|
||||||
|
|
||||||
if not message_ids:
|
|
||||||
return []
|
|
||||||
|
|
||||||
messages = self._safe_execute(model_name, 'read', message_ids, ["id", "subject", "body", "author_id", "date"])
|
|
||||||
if messages is None:
|
|
||||||
return []
|
|
||||||
|
|
||||||
formatted_messages = []
|
|
||||||
for msg in messages:
|
|
||||||
# Utiliser la fonction clean_html de data_filter
|
|
||||||
from data_filter import clean_html
|
|
||||||
cleaned_content = clean_html(msg["body"])
|
|
||||||
|
|
||||||
if cleaned_content:
|
|
||||||
formatted_messages.append({
|
|
||||||
"ID Message": msg["id"],
|
|
||||||
"Sujet": msg["subject"] or "Sans sujet",
|
|
||||||
"Contenu": cleaned_content,
|
|
||||||
"Auteur": msg["author_id"][1] if msg["author_id"] else "Inconnu",
|
|
||||||
"Date": msg["date"]
|
|
||||||
})
|
|
||||||
|
|
||||||
return formatted_messages
|
|
||||||
|
|
||||||
def search_tickets_by_fields(self, field_criteria, limit=50):
|
|
||||||
"""Recherche des tickets selon des critères de champs"""
|
|
||||||
# Construire le domaine de recherche
|
|
||||||
domain = []
|
|
||||||
for field, value in field_criteria.items():
|
|
||||||
domain.append((field, '=', value))
|
|
||||||
|
|
||||||
print(f"\nRecherche de tickets avec les critères: {field_criteria}")
|
|
||||||
|
|
||||||
# Rechercher les tickets correspondants
|
|
||||||
ticket_ids = self._safe_execute(self.model_name, 'search', domain, 0, limit)
|
|
||||||
if not ticket_ids:
|
|
||||||
print("Aucun ticket ne correspond aux critères de recherche.")
|
|
||||||
return []
|
|
||||||
|
|
||||||
print(f"Nombre de tickets trouvés: {len(ticket_ids)}")
|
|
||||||
|
|
||||||
# Récupérer tous les tickets trouvés
|
|
||||||
tickets = []
|
|
||||||
for ticket_id in ticket_ids:
|
|
||||||
ticket = self.get_ticket_by_id(ticket_id)
|
|
||||||
if ticket:
|
|
||||||
tickets.append(ticket)
|
|
||||||
|
|
||||||
return tickets
|
|
||||||
|
|
||||||
def export_tickets_by_project_and_stage(self, project_id, selected_stage_ids=None):
|
|
||||||
"""Exporte les tickets d'un projet classés par étape
|
|
||||||
|
|
||||||
Args:
|
|
||||||
project_id (int): L'ID du projet
|
|
||||||
selected_stage_ids (list, optional): Liste des IDs d'étapes à inclure. Si None, toutes les étapes sont incluses.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
# Convertir project_id en entier
|
|
||||||
project_id = int(project_id)
|
|
||||||
|
|
||||||
# Vérifier si le projet existe
|
|
||||||
projects = self._safe_execute('project.project', 'search_read', [('id', '=', project_id)], ['id', 'name'])
|
|
||||||
if not projects:
|
|
||||||
print(f"Aucun projet trouvé avec l'ID: {project_id}")
|
|
||||||
return
|
|
||||||
|
|
||||||
project_name = projects[0]['name']
|
|
||||||
print(f"\nRécupération des tickets du projet: {project_name} (ID: {project_id})")
|
|
||||||
|
|
||||||
# Construire le domaine de recherche
|
|
||||||
domain = [('project_id', '=', project_id)]
|
|
||||||
|
|
||||||
# Si des étapes spécifiques sont sélectionnées, ajouter à la condition
|
|
||||||
if selected_stage_ids and len(selected_stage_ids) > 0:
|
|
||||||
domain.append(('stage_id', 'in', selected_stage_ids))
|
|
||||||
print(f"Filtrage sur {len(selected_stage_ids)} étapes sélectionnées")
|
|
||||||
|
|
||||||
ticket_ids = self._safe_execute(self.model_name, 'search', domain, 0, 1000)
|
|
||||||
|
|
||||||
if not ticket_ids:
|
|
||||||
print(f"Aucun ticket trouvé avec les critères spécifiés.")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Récupérer les tickets avec les champs essentiels
|
|
||||||
fields_to_read = ['id', 'name', 'code', 'stage_id', 'date_deadline',
|
|
||||||
'description', 'priority', 'sequence', 'message_ids']
|
|
||||||
|
|
||||||
tickets_data = self._safe_execute(self.model_name, 'read', ticket_ids, fields_to_read)
|
|
||||||
|
|
||||||
if not tickets_data:
|
|
||||||
print("Erreur lors de la récupération des données des tickets.")
|
|
||||||
return
|
|
||||||
|
|
||||||
print(f"Nombre de tickets trouvés: {len(tickets_data)}")
|
|
||||||
|
|
||||||
# Convertir les tickets au format approprié et les filtrer
|
|
||||||
formatted_tickets = []
|
|
||||||
for ticket in tickets_data:
|
|
||||||
formatted_ticket = {
|
|
||||||
"ID du Ticket": ticket["id"],
|
|
||||||
"Nom": ticket["name"],
|
|
||||||
"Code": ticket.get("code", "N/A"),
|
|
||||||
"Date Limite": ticket.get("date_deadline", "Non défini"),
|
|
||||||
"Champs Simples": {
|
|
||||||
"description": ticket.get("description", ""),
|
|
||||||
"priority": ticket.get("priority", ""),
|
|
||||||
"sequence": ticket.get("sequence", "")
|
|
||||||
},
|
|
||||||
"Champs Relationnels": {
|
|
||||||
"project_id": [project_id, project_name],
|
|
||||||
"stage_id": ticket.get("stage_id", [0, "Inconnu"])
|
|
||||||
},
|
|
||||||
"Discussions": []
|
|
||||||
}
|
|
||||||
|
|
||||||
# Récupérer les discussions si nécessaire
|
|
||||||
if ticket.get("message_ids"):
|
|
||||||
formatted_ticket["Discussions"] = self.get_ticket_discussions(ticket["message_ids"])
|
|
||||||
|
|
||||||
# Filtrer le ticket
|
|
||||||
filtered_ticket = filter_ticket_data(formatted_ticket)
|
|
||||||
formatted_tickets.append(filtered_ticket)
|
|
||||||
|
|
||||||
if not formatted_tickets:
|
|
||||||
print("Aucun ticket n'a pu être formaté correctement.")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Créer un répertoire pour le projet avec son nom pour plus de clarté
|
|
||||||
safe_project_name = project_name.replace('/', '_').replace(' ', '_').replace('\\', '_')
|
|
||||||
project_dir = ensure_export_directory(f"project_{project_id}_{safe_project_name}")
|
|
||||||
|
|
||||||
print(f"\nExportation des tickets pour le projet {project_name} (ID: {project_id}):")
|
|
||||||
|
|
||||||
# Classer les tickets par stage_id
|
|
||||||
tickets_by_stage = {}
|
|
||||||
for ticket in formatted_tickets:
|
|
||||||
# Vérifier que stage_id existe dans les champs relationnels
|
|
||||||
if 'Champs Relationnels' in ticket and 'stage_id' in ticket['Champs Relationnels']:
|
|
||||||
stage_data = ticket['Champs Relationnels']['stage_id']
|
|
||||||
|
|
||||||
if isinstance(stage_data, list) and len(stage_data) > 0:
|
|
||||||
stage_id = stage_data[0]
|
|
||||||
stage_name = stage_data[1] if len(stage_data) > 1 else "Inconnu"
|
|
||||||
else:
|
|
||||||
# Si stage_id n'est pas une liste, utiliser une valeur par défaut
|
|
||||||
stage_id = 0
|
|
||||||
stage_name = "Inconnu"
|
|
||||||
|
|
||||||
key = f"{stage_id}_{stage_name}"
|
|
||||||
if key not in tickets_by_stage:
|
|
||||||
tickets_by_stage[key] = []
|
|
||||||
tickets_by_stage[key].append(ticket)
|
|
||||||
else:
|
|
||||||
# Si le ticket n'a pas de stage_id, le mettre dans "Non classé"
|
|
||||||
key = "0_Non_classé"
|
|
||||||
if key not in tickets_by_stage:
|
|
||||||
tickets_by_stage[key] = []
|
|
||||||
tickets_by_stage[key].append(ticket)
|
|
||||||
|
|
||||||
# Vérifier si des tickets ont été classés
|
|
||||||
if not tickets_by_stage:
|
|
||||||
print("Aucun ticket n'a pu être classé par stage_id.")
|
|
||||||
# Sauvegarde tous les tickets dans un seul fichier
|
|
||||||
all_tickets_file = os.path.join(project_dir, "all_tickets.json")
|
|
||||||
save_json(all_tickets_file, formatted_tickets)
|
|
||||||
print(f"Tous les tickets ont été sauvegardés dans {all_tickets_file}")
|
|
||||||
return
|
|
||||||
|
|
||||||
# Créer des répertoires pour chaque stage_id et sauvegarder les tickets
|
|
||||||
for stage_key, stage_tickets in tickets_by_stage.items():
|
|
||||||
stage_parts = stage_key.split('_', 1)
|
|
||||||
stage_id = stage_parts[0]
|
|
||||||
stage_name = stage_parts[1] if len(stage_parts) > 1 else "Inconnu"
|
|
||||||
safe_stage_name = stage_name.replace('/', '_').replace('\\', '_')
|
|
||||||
stage_dir = os.path.join(project_dir, f"{stage_id}_{safe_stage_name}")
|
|
||||||
os.makedirs(stage_dir, exist_ok=True)
|
|
||||||
|
|
||||||
print(f"- Stage '{stage_name}' (ID: {stage_id}): {len(stage_tickets)} tickets")
|
|
||||||
|
|
||||||
# Sauvegarder tous les tickets du stage dans un fichier unique
|
|
||||||
all_tickets_file = os.path.join(stage_dir, f"all_tickets.json")
|
|
||||||
save_json(all_tickets_file, stage_tickets)
|
|
||||||
|
|
||||||
# Sauvegarder chaque ticket individuellement
|
|
||||||
for ticket in stage_tickets:
|
|
||||||
ticket_code = ticket.get('Code', 'N/A')
|
|
||||||
ticket_id = ticket.get('ID du Ticket', 'N/A')
|
|
||||||
ticket_file = os.path.join(stage_dir, f"ticket_{ticket_code}_{ticket_id}.json")
|
|
||||||
save_json(ticket_file, ticket)
|
|
||||||
|
|
||||||
print(f" Tickets sauvegardés dans {stage_dir}/")
|
|
||||||
|
|
||||||
print(f"\nExportation terminée dans {project_dir}/")
|
|
||||||
|
|
||||||
except ValueError:
|
|
||||||
print(f"Erreur: Le project_id '{project_id}' n'est pas un nombre valide.")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Erreur lors de l'exportation des tickets: {e}")
|
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
||||||
|
|
||||||
def get_available_projects(self):
|
|
||||||
"""Récupère la liste des projets disponibles"""
|
|
||||||
projects = self._safe_execute('project.project', 'search_read', [], ['id', 'name'])
|
|
||||||
if not projects:
|
|
||||||
print("Aucun projet disponible.")
|
|
||||||
return {}
|
|
||||||
|
|
||||||
projects_dict = {}
|
|
||||||
print("\nProjets disponibles:")
|
|
||||||
for project in projects:
|
|
||||||
project_id = project['id']
|
|
||||||
project_name = project['name']
|
|
||||||
projects_dict[project_id] = project_name
|
|
||||||
print(f"ID: {project_id} - {project_name}")
|
|
||||||
|
|
||||||
return projects_dict
|
|
||||||
|
|
||||||
def get_project_tickets_summary(self, project_id):
|
def get_project_tickets_summary(self, project_id):
|
||||||
"""Récupère un résumé des tickets d'un projet pour permettre la sélection"""
|
"""Récupère un résumé des tickets d'un projet pour permettre la sélection"""
|
||||||
domain = [('project_id', '=', project_id)]
|
domain = [('project_id', '=', project_id)]
|
||||||
@ -354,7 +68,6 @@ class TicketManager:
|
|||||||
print(f"Aucun ticket trouvé pour le projet ID: {project_id}")
|
print(f"Aucun ticket trouvé pour le projet ID: {project_id}")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# Récupérer des informations résumées sur les tickets
|
|
||||||
fields_to_read = ['id', 'name', 'code', 'stage_id', 'date_deadline']
|
fields_to_read = ['id', 'name', 'code', 'stage_id', 'date_deadline']
|
||||||
tickets_data = self._safe_execute(self.model_name, 'read', ticket_ids, fields_to_read)
|
tickets_data = self._safe_execute(self.model_name, 'read', ticket_ids, fields_to_read)
|
||||||
|
|
||||||
@ -362,7 +75,6 @@ class TicketManager:
|
|||||||
print("Erreur lors de la récupération des données des tickets.")
|
print("Erreur lors de la récupération des données des tickets.")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# Formater les données pour l'affichage
|
|
||||||
summary_tickets = []
|
summary_tickets = []
|
||||||
for ticket in tickets_data:
|
for ticket in tickets_data:
|
||||||
stage_name = "Non défini"
|
stage_name = "Non défini"
|
||||||
@ -379,51 +91,41 @@ class TicketManager:
|
|||||||
})
|
})
|
||||||
|
|
||||||
return summary_tickets
|
return summary_tickets
|
||||||
|
|
||||||
def get_project_stages(self, project_id):
|
def export_tickets_by_project_and_stage(self, project_id, selected_stage_ids=None):
|
||||||
"""Récupère les étapes (stage_id) disponibles pour un projet donné
|
"""Exporte les tickets d'un projet classés par étape"""
|
||||||
|
project_data = self._safe_execute('project.project', 'search_read', [('id', '=', project_id)], ['id', 'name'])
|
||||||
|
if not project_data:
|
||||||
|
print(f"Projet ID {project_id} introuvable")
|
||||||
|
return
|
||||||
|
|
||||||
Args:
|
project_name = project_data[0]['name']
|
||||||
project_id (int): L'ID du projet
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict: Un dictionnaire des étapes {stage_id: stage_name}
|
|
||||||
"""
|
|
||||||
# Récupérer les tickets du projet
|
|
||||||
domain = [('project_id', '=', project_id)]
|
domain = [('project_id', '=', project_id)]
|
||||||
|
if selected_stage_ids:
|
||||||
|
domain.append(('stage_id', 'in', selected_stage_ids))
|
||||||
|
|
||||||
ticket_ids = self._safe_execute(self.model_name, 'search', domain, 0, 1000)
|
ticket_ids = self._safe_execute(self.model_name, 'search', domain, 0, 1000)
|
||||||
|
|
||||||
if not ticket_ids:
|
if not ticket_ids:
|
||||||
print(f"Aucun ticket trouvé pour le projet ID: {project_id}")
|
print("Aucun ticket trouvé")
|
||||||
return {}
|
return
|
||||||
|
|
||||||
# Récupérer uniquement les stage_id des tickets
|
tickets = [self.get_ticket_by_id(ticket_id) for ticket_id in ticket_ids]
|
||||||
tickets_data = self._safe_execute(self.model_name, 'read', ticket_ids, ['stage_id'])
|
|
||||||
|
|
||||||
if not tickets_data:
|
tickets_by_stage = {}
|
||||||
print("Erreur lors de la récupération des étapes.")
|
for ticket in tickets:
|
||||||
return {}
|
stage_id = ticket["Champs Relationnels"].get("stage_id", [0, "Non classé"])[0]
|
||||||
|
stage_name = ticket["Champs Relationnels"].get("stage_id", [0, "Non classé"])[1]
|
||||||
|
key = f"{stage_id}_{stage_name}"
|
||||||
|
|
||||||
|
if key not in tickets_by_stage:
|
||||||
|
tickets_by_stage[key] = []
|
||||||
|
tickets_by_stage[key].append(ticket)
|
||||||
|
|
||||||
# Extraire les stage_id uniques
|
project_dir = ensure_export_directory(f"project_{project_id}_{project_name.replace(' ', '_')}")
|
||||||
stage_ids = set()
|
|
||||||
for ticket in tickets_data:
|
|
||||||
if ticket.get('stage_id'):
|
|
||||||
stage_ids.add(ticket['stage_id'][0])
|
|
||||||
|
|
||||||
if not stage_ids:
|
for stage_key, stage_tickets in tickets_by_stage.items():
|
||||||
print("Aucune étape trouvée pour ce projet.")
|
stage_dir = os.path.join(project_dir, stage_key)
|
||||||
return {}
|
os.makedirs(stage_dir, exist_ok=True)
|
||||||
|
save_json(os.path.join(stage_dir, "all_tickets.json"), stage_tickets)
|
||||||
|
|
||||||
# Récupérer les noms des étapes
|
print(f"Exportation terminée dans {project_dir}/")
|
||||||
stages_data = self._safe_execute('project.task.type', 'read', list(stage_ids), ['id', 'name'])
|
|
||||||
|
|
||||||
if not stages_data:
|
|
||||||
print("Erreur lors de la récupération des noms des étapes.")
|
|
||||||
return {}
|
|
||||||
|
|
||||||
# Créer un dictionnaire des étapes
|
|
||||||
stages_dict = {}
|
|
||||||
for stage in stages_data:
|
|
||||||
stages_dict[stage['id']] = stage['name']
|
|
||||||
|
|
||||||
return stages_dict
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user