1704-08:48

This commit is contained in:
Ladebeze66 2025-04-17 08:48:26 +02:00
parent c1e4389528
commit 9885f14e3b
145 changed files with 10061 additions and 652 deletions

View File

@ -23,7 +23,7 @@ class AgentReportGenerator(BaseAgent):
# Configuration locale de l'agent
self.temperature = 0.2
self.top_p = 0.9
self.max_tokens = 10000
self.max_tokens = 8000
# Prompt système principal
self.system_prompt = """Tu es un expert en génération de rapports techniques pour BRG-Lab pour la société CBAO.

View File

@ -0,0 +1,301 @@
from ..base_agent import BaseAgent
from typing import Dict, Any, Optional
import logging
import json
import os
import sys
from datetime import datetime
# Ajout du chemin des utilitaires au PATH pour pouvoir les importer
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from loaders.ticket_data_loader import TicketDataLoader
logger = logging.getLogger("AgentTicketAnalyser")
class AgentTicketAnalyser(BaseAgent):
"""
Agent pour analyser les tickets (JSON ou Markdown) et en extraire les informations importantes.
Remplace l'ancien AgentJsonAnalyser avec des fonctionnalités améliorées.
"""
def __init__(self, llm):
super().__init__("AgentTicketAnalyser", llm)
# Configuration locale de l'agent
self.temperature = 0.1 # Besoin d'analyse très précise
self.top_p = 0.8
self.max_tokens = 8000
# Prompt système optimisé
self.system_prompt = """Tu es un expert en analyse de tickets pour le support informatique de BRG-Lab pour la société CBAO.
Tu interviens avant l'analyse des captures d'écran pour contextualiser le ticket, identifier les questions posées, et structurer les échanges de manière claire.
Ta mission principale :
1. Identifier le client et le contexte du ticket (demande "name" et "description")
- Récupère le nom de l'auteur si présent
- Indique si un `user_id` est disponible
- Conserve uniquement les informations d'identification utiles (pas d'adresse ou signature de mail inutile)
2. Mettre en perspective le `name` du ticket
- Il peut contenir une ou plusieurs questions implicites
- Reformule ces questions de façon explicite
3. Analyser la `description`
- Elle fournit souvent le vrai point d'entrée technique
- Repère les formulations interrogatives ou les demandes spécifiques
- Identifie si cette partie complète ou précise les questions du nom
4. Structurer le fil de discussion
- Conserve uniquement les échanges pertinents
-Conserve les questions soulevés par "name" ou "description"
- CONSERVE ABSOLUMENT les références documentation, FAQ, liens utiles et manuels
- Identifie clairement chaque intervenant (client / support)
- Classe les informations par ordre chronologique avec date et rôle
5. Préparer la transmission à l'agent suivant
- Préserve tous les éléments utiles à l'analyse d'image : modules cités, options évoquées, comportements décrits
- Mentionne si des images sont attachées au ticket
Structure ta réponse :
1. Résumé du contexte
- Client (nom, email si disponible)
- Sujet du ticket reformulé en une ou plusieurs questions
- Description technique synthétique
2. Informations techniques détectées
- Logiciels/modules mentionnés
- Paramètres évoqués
- Fonctionnalités impactées
- Conditions spécifiques (multi-laboratoire, utilisateur non valide, etc.)
3. Fil de discussion (filtrée, nettoyée, classée)
- Intervenant (Client/Support)
- Date et contenu de chaque échange
- Résumés techniques
- INCLURE TOUS les liens documentaires (manuel, FAQ, documentation technique)
4. Éléments liés à l'analyse visuelle
- Nombre d'images attachées
- Références aux interfaces ou options à visualiser
- Points à vérifier dans les captures (listes incomplètes, cases à cocher, utilisateurs grisés, etc.)
IMPORTANT :
- Ne propose aucune solution ni interprétation
- Ne génère pas de tableau
- Reste strictement factuel en te basant uniquement sur les informations fournies
- Ne reformule pas les messages, conserve les formulations exactes sauf nettoyage de forme"""
# Initialiser le loader de données
self.ticket_loader = TicketDataLoader()
# Appliquer la configuration au LLM
self._appliquer_config_locale()
logger.info("AgentTicketAnalyser initialisé")
def _appliquer_config_locale(self) -> None:
"""
Applique la configuration locale au modèle LLM.
"""
# Appliquer le prompt système
if hasattr(self.llm, "prompt_system"):
self.llm.prompt_system = self.system_prompt
# Appliquer les paramètres
if hasattr(self.llm, "configurer"):
params = {
"temperature": self.temperature,
"top_p": self.top_p,
"max_tokens": self.max_tokens
}
self.llm.configurer(**params)
def executer(self, ticket_data: Dict[str, Any]) -> str:
"""
Analyse un ticket pour en extraire les informations pertinentes
Args:
ticket_data: Dictionnaire contenant les données du ticket à analyser
ou chemin vers un fichier de ticket (JSON ou Markdown)
Returns:
Réponse formatée contenant l'analyse du ticket
"""
# Détecter si ticket_data est un chemin de fichier ou un dictionnaire
if isinstance(ticket_data, str) and os.path.exists(ticket_data):
try:
ticket_data = self.ticket_loader.charger(ticket_data)
logger.info(f"Données chargées depuis le fichier: {ticket_data}")
except Exception as e:
error_message = f"Erreur lors du chargement du fichier: {str(e)}"
logger.error(error_message)
return f"ERREUR: {error_message}"
# Vérifier que les données sont bien un dictionnaire
if not isinstance(ticket_data, dict):
error_message = "Les données du ticket doivent être un dictionnaire ou un chemin de fichier valide"
logger.error(error_message)
return f"ERREUR: {error_message}"
ticket_code = ticket_data.get('code', 'Inconnu')
logger.info(f"Analyse du ticket: {ticket_code}")
print(f"AgentTicketAnalyser: Analyse du ticket {ticket_code}")
# Récupérer les métadonnées sur la source des données
source_format = "inconnu"
source_file = "non spécifié"
if "metadata" in ticket_data and isinstance(ticket_data["metadata"], dict):
source_format = ticket_data["metadata"].get("format", "inconnu")
source_file = ticket_data["metadata"].get("source_file", "non spécifié")
logger.info(f"Format source: {source_format}, Fichier source: {source_file}")
# Préparer le ticket pour l'analyse
ticket_formate = self._formater_ticket_pour_analyse(ticket_data)
# Créer le prompt pour l'analyse, adapté au format source
prompt = f"""Analyse ce ticket pour en extraire les informations clés et préparer une synthèse structurée.
SOURCE: {source_format.upper()}
{ticket_formate}
RAPPEL IMPORTANT:
- CONSERVE TOUS les liens (FAQ, documentation, manuels) présents dans les messages
- Extrais et organise chronologiquement les échanges client/support
- Identifie les éléments techniques à observer dans les captures d'écran
- Reste factuel et précis sans proposer de solution"""
try:
logger.info("Interrogation du LLM")
response = self.llm.interroger(prompt)
logger.info(f"Réponse reçue: {len(response)} caractères")
print(f" Analyse terminée: {len(response)} caractères")
except Exception as e:
error_message = f"Erreur lors de l'analyse du ticket: {str(e)}"
logger.error(error_message)
response = f"ERREUR: {error_message}"
print(f" ERREUR: {error_message}")
# Enregistrer l'historique avec le prompt complet pour la traçabilité
self.ajouter_historique("analyse_ticket",
{
"ticket_id": ticket_code,
"format_source": source_format,
"source_file": source_file,
"prompt": prompt,
"temperature": self.temperature,
"top_p": self.top_p,
"max_tokens": self.max_tokens,
"timestamp": self._get_timestamp()
},
response)
return response
def _formater_ticket_pour_analyse(self, ticket_data: Dict) -> str:
"""
Formate les données du ticket pour l'analyse LLM, avec une meilleure
gestion des différents formats et structures de données.
Args:
ticket_data: Les données du ticket
Returns:
Représentation textuelle formatée du ticket
"""
# Initialiser avec les informations de base
ticket_name = ticket_data.get('name', 'Sans titre')
ticket_code = ticket_data.get('code', 'Inconnu')
info = f"## TICKET {ticket_code}: {ticket_name}\n\n"
info += f"## NOM DE LA DEMANDE (PROBLÈME INITIAL)\n{ticket_name}\n\n"
# Ajouter la description
description = ticket_data.get('description', '')
if description:
info += f"## DESCRIPTION DU PROBLÈME\n{description}\n\n"
# Ajouter les informations du ticket (exclure certains champs spécifiques)
champs_a_exclure = ['code', 'name', 'description', 'messages', 'metadata']
info += "## INFORMATIONS TECHNIQUES DU TICKET\n"
for key, value in ticket_data.items():
if key not in champs_a_exclure and value:
# Formater les valeurs complexes si nécessaire
if isinstance(value, (dict, list)):
value = json.dumps(value, ensure_ascii=False, indent=2)
info += f"- {key}: {value}\n"
info += "\n"
# Ajouter les messages (conversations) avec un formatage amélioré pour distinguer client/support
messages = ticket_data.get('messages', [])
if messages:
info += "## CHRONOLOGIE DES ÉCHANGES CLIENT/SUPPORT\n"
for i, msg in enumerate(messages):
# Vérifier que le message est bien un dictionnaire
if not isinstance(msg, dict):
continue
sender = msg.get('from', 'Inconnu')
date = msg.get('date', 'Date inconnue')
content = msg.get('content', '')
# Identifier si c'est client ou support
sender_type = "CLIENT" if "client" in sender.lower() else "SUPPORT" if "support" in sender.lower() else "AUTRE"
# Formater correctement la date si possible
try:
if date != 'Date inconnue':
# Essayer différents formats de date
for date_format in ['%Y-%m-%d %H:%M:%S', '%Y-%m-%d', '%d/%m/%Y']:
try:
date_obj = datetime.strptime(date, date_format)
date = date_obj.strftime('%d/%m/%Y %H:%M')
break
except ValueError:
continue
except Exception:
pass # Garder la date d'origine en cas d'erreur
info += f"### Message {i+1} - [{sender_type}] De: {sender} - Date: {date}\n{content}\n\n"
# Ajouter les métadonnées techniques si présentes
metadata = ticket_data.get('metadata', {})
# Exclure certaines métadonnées internes
for key in ['source_file', 'format']:
if key in metadata:
metadata.pop(key)
if metadata:
info += "## MÉTADONNÉES TECHNIQUES\n"
for key, value in metadata.items():
if isinstance(value, (dict, list)):
value = json.dumps(value, ensure_ascii=False, indent=2)
info += f"- {key}: {value}\n"
info += "\n"
return info
def analyser_depuis_fichier(self, chemin_fichier: str) -> str:
"""
Analyse un ticket à partir d'un fichier (JSON ou Markdown)
Args:
chemin_fichier: Chemin vers le fichier à analyser
Returns:
Résultat de l'analyse
"""
try:
ticket_data = self.ticket_loader.charger(chemin_fichier)
return self.executer(ticket_data)
except Exception as e:
error_message = f"Erreur lors de l'analyse du fichier {chemin_fichier}: {str(e)}"
logger.error(error_message)
return f"ERREUR: {error_message}"
def _get_timestamp(self) -> str:
"""Retourne un timestamp au format YYYYMMDD_HHMMSS"""
return datetime.now().strftime("%Y%m%d_%H%M%S")

View File

@ -1,13 +1,9 @@
from ..base_agent import BaseAgent
from typing import Dict, Any, Optional
from typing import Dict, Any
import logging
import json
import os
import sys
from datetime import datetime
# Ajout du chemin des utilitaires au PATH pour pouvoir les importer
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from loaders.ticket_data_loader import TicketDataLoader
logger = logging.getLogger("AgentTicketAnalyser")
@ -15,287 +11,183 @@ logger = logging.getLogger("AgentTicketAnalyser")
class AgentTicketAnalyser(BaseAgent):
"""
Agent pour analyser les tickets (JSON ou Markdown) et en extraire les informations importantes.
Remplace l'ancien AgentJsonAnalyser avec des fonctionnalités améliorées.
Utilisé pour contextualiser les tickets avant l'analyse des captures d'écran.
"""
def __init__(self, llm):
super().__init__("AgentTicketAnalyser", llm)
# Configuration locale de l'agent
self.temperature = 0.1 # Besoin d'analyse très précise
# Configuration adaptée à l'analyse structurée pour Mistral Large
self.temperature = 0.1
self.top_p = 0.8
self.max_tokens = 8000
# Prompt système optimisé
self.system_prompt = """Tu es un expert en analyse de tickets pour le support informatique de BRG-Lab pour la société CBAO.
Tu interviens avant l'analyse des captures d'écran pour contextualiser le ticket, identifier les questions posées, et structurer les échanges de manière claire.
self.max_tokens = 6000
Ta mission principale :
# Prompt système clair, structuré, optimisé pour une analyse exhaustive
self.system_prompt = """Tu es un expert en analyse de tickets pour le support informatique de BRG-Lab (client : CBAO).
1. Identifier le client et le contexte du ticket (demande "name" et "description")
- Récupère le nom de l'auteur si présent
- Indique si un `user_id` est disponible
- Conserve uniquement les informations d'identification utiles (pas d'adresse ou signature de mail inutile)
2. Mettre en perspective le `name` du ticket
- Il peut contenir une ou plusieurs questions implicites
- Reformule ces questions de façon explicite
3. Analyser la `description`
- Elle fournit souvent le vrai point d'entrée technique
- Repère les formulations interrogatives ou les demandes spécifiques
- Identifie si cette partie complète ou précise les questions du nom
4. Structurer le fil de discussion
- Conserve uniquement les échanges pertinents
-Conserve les questions soulevés par "name" ou "description"
- CONSERVE ABSOLUMENT les références documentation, FAQ, liens utiles et manuels
- Identifie clairement chaque intervenant (client / support)
- Classe les informations par ordre chronologique avec date et rôle
5. Préparer la transmission à l'agent suivant
- Préserve tous les éléments utiles à l'analyse d'image : modules cités, options évoquées, comportements décrits
- Mentionne si des images sont attachées au ticket
Structure ta réponse :
Tu dois :
1. Identifier le client et résumer la demande.
2. Reformuler les questions implicites du ticket (à partir du `name` et `description`).
3. Nettoyer et structurer les échanges client/support en conservant les informations utiles (liens, modules, options, erreurs).
4. Extraire les éléments à observer dans les captures (pour l'agent image).
Structure de sortie :
1. Résumé du contexte
- Client (nom, email si disponible)
- Sujet du ticket reformulé en une ou plusieurs questions
- Description technique synthétique
2. Informations techniques détectées
- Logiciels/modules mentionnés
- Paramètres évoqués
- Fonctionnalités impactées
- Conditions spécifiques (multi-laboratoire, utilisateur non valide, etc.)
3. Fil de discussion (filtrée, nettoyée, classée)
- Intervenant (Client/Support)
- Date et contenu de chaque échange
- Résumés techniques
- INCLURE TOUS les liens documentaires (manuel, FAQ, documentation technique)
4. Éléments liés à l'analyse visuelle
- Nombre d'images attachées
- Références aux interfaces ou options à visualiser
- Points à vérifier dans les captures (listes incomplètes, cases à cocher, utilisateurs grisés, etc.)
3. Fil de discussion (filtré, classé, nettoyé)
4. Points visuels à analyser (éléments à retrouver dans les captures)
IMPORTANT :
- Ne propose aucune solution ni interprétation
- Ne génère pas de tableau
- Reste strictement factuel en te basant uniquement sur les informations fournies
- Ne reformule pas les messages, conserve les formulations exactes sauf nettoyage de forme"""
# Initialiser le loader de données
- Ne propose pas de solution
- Garde tous les liens et noms de modules
- Ne transforme pas les propos sauf pour supprimer les bruits inutiles (signatures, mails automatiques)
- Ne reformule pas les messages sauf si cela clarifie les intentions sans altérer leur sens
"""
self.ticket_loader = TicketDataLoader()
# Appliquer la configuration au LLM
self._appliquer_config_locale()
logger.info("AgentTicketAnalyser initialisé")
def _appliquer_config_locale(self) -> None:
"""
Applique la configuration locale au modèle LLM.
"""
# Appliquer le prompt système
"""Applique les paramètres et le prompt système au modèle"""
if hasattr(self.llm, "prompt_system"):
self.llm.prompt_system = self.system_prompt
# Appliquer les paramètres
if hasattr(self.llm, "configurer"):
params = {
"temperature": self.temperature,
"top_p": self.top_p,
"max_tokens": self.max_tokens
}
self.llm.configurer(**params)
self.llm.configurer(
temperature=self.temperature,
top_p=self.top_p,
max_tokens=self.max_tokens
)
def executer(self, ticket_data: Dict[str, Any]) -> str:
"""
Analyse un ticket pour en extraire les informations pertinentes
Args:
ticket_data: Dictionnaire contenant les données du ticket à analyser
ou chemin vers un fichier de ticket (JSON ou Markdown)
Returns:
Réponse formatée contenant l'analyse du ticket
"""
# Détecter si ticket_data est un chemin de fichier ou un dictionnaire
"""Analyse le ticket donné sous forme de dict"""
if isinstance(ticket_data, str) and os.path.exists(ticket_data):
try:
ticket_data = self.ticket_loader.charger(ticket_data)
logger.info(f"Données chargées depuis le fichier: {ticket_data}")
except Exception as e:
error_message = f"Erreur lors du chargement du fichier: {str(e)}"
logger.error(error_message)
return f"ERREUR: {error_message}"
# Vérifier que les données sont bien un dictionnaire
ticket_data = self.ticket_loader.charger(ticket_data)
if not isinstance(ticket_data, dict):
error_message = "Les données du ticket doivent être un dictionnaire ou un chemin de fichier valide"
logger.error(error_message)
return f"ERREUR: {error_message}"
ticket_code = ticket_data.get('code', 'Inconnu')
logger.info(f"Analyse du ticket: {ticket_code}")
print(f"AgentTicketAnalyser: Analyse du ticket {ticket_code}")
# Récupérer les métadonnées sur la source des données
source_format = "inconnu"
source_file = "non spécifié"
if "metadata" in ticket_data and isinstance(ticket_data["metadata"], dict):
source_format = ticket_data["metadata"].get("format", "inconnu")
source_file = ticket_data["metadata"].get("source_file", "non spécifié")
logger.info(f"Format source: {source_format}, Fichier source: {source_file}")
# Préparer le ticket pour l'analyse
ticket_formate = self._formater_ticket_pour_analyse(ticket_data)
# Créer le prompt pour l'analyse, adapté au format source
prompt = f"""Analyse ce ticket pour en extraire les informations clés et préparer une synthèse structurée.
logger.error("Les données du ticket ne sont pas valides")
return "ERREUR: Format de ticket invalide"
SOURCE: {source_format.upper()}
ticket_code = ticket_data.get("code", "Inconnu")
logger.info(f"Analyse du ticket {ticket_code}")
print(f"AgentTicketAnalyser: analyse du ticket {ticket_code}")
{ticket_formate}
prompt = self._generer_prompt(ticket_data)
RAPPEL IMPORTANT:
- CONSERVE TOUS les liens (FAQ, documentation, manuels) présents dans les messages
- Extrais et organise chronologiquement les échanges client/support
- Identifie les éléments techniques à observer dans les captures d'écran
- Reste factuel et précis sans proposer de solution"""
try:
logger.info("Interrogation du LLM")
response = self.llm.interroger(prompt)
logger.info(f"Réponse reçue: {len(response)} caractères")
logger.info("Analyse du ticket terminée avec succès")
print(f" Analyse terminée: {len(response)} caractères")
except Exception as e:
error_message = f"Erreur lors de l'analyse du ticket: {str(e)}"
logger.error(error_message)
response = f"ERREUR: {error_message}"
print(f" ERREUR: {error_message}")
# Enregistrer l'historique avec le prompt complet pour la traçabilité
self.ajouter_historique("analyse_ticket",
{
"ticket_id": ticket_code,
"format_source": source_format,
"source_file": source_file,
"prompt": prompt,
"temperature": self.temperature,
"top_p": self.top_p,
"max_tokens": self.max_tokens,
"timestamp": self._get_timestamp()
},
response)
logger.error(f"Erreur d'analyse: {str(e)}")
return f"ERREUR: {str(e)}"
self.ajouter_historique(
"analyse_ticket",
{
"ticket_id": ticket_code,
"prompt": prompt,
"timestamp": self._get_timestamp()
},
response
)
return response
def _formater_ticket_pour_analyse(self, ticket_data: Dict) -> str:
def _generer_prompt(self, ticket_data: Dict[str, Any]) -> str:
"""
Formate les données du ticket pour l'analyse LLM, avec une meilleure
gestion des différents formats et structures de données.
Args:
ticket_data: Les données du ticket
Returns:
Représentation textuelle formatée du ticket
Prépare un prompt texte structuré à partir des données brutes du ticket.
"""
# Initialiser avec les informations de base
ticket_name = ticket_data.get('name', 'Sans titre')
ticket_code = ticket_data.get('code', 'Inconnu')
info = f"## TICKET {ticket_code}: {ticket_name}\n\n"
info += f"## NOM DE LA DEMANDE (PROBLÈME INITIAL)\n{ticket_name}\n\n"
# Ajouter la description
description = ticket_data.get('description', '')
ticket_code = ticket_data.get("code", "Inconnu")
name = ticket_data.get("name", "").strip()
description = ticket_data.get("description", "").strip()
# En-tête
texte = f"### TICKET {ticket_code}\n\n"
if name:
texte += f"#### NOM DU TICKET\n{name}\n\n"
if description:
info += f"## DESCRIPTION DU PROBLÈME\n{description}\n\n"
# Ajouter les informations du ticket (exclure certains champs spécifiques)
champs_a_exclure = ['code', 'name', 'description', 'messages', 'metadata']
info += "## INFORMATIONS TECHNIQUES DU TICKET\n"
for key, value in ticket_data.items():
if key not in champs_a_exclure and value:
# Formater les valeurs complexes si nécessaire
if isinstance(value, (dict, list)):
value = json.dumps(value, ensure_ascii=False, indent=2)
info += f"- {key}: {value}\n"
info += "\n"
# Ajouter les messages (conversations) avec un formatage amélioré pour distinguer client/support
messages = ticket_data.get('messages', [])
texte += f"#### DESCRIPTION\n{description}\n\n"
# Informations techniques utiles (hors champs exclus)
champs_exclus = {"code", "name", "description", "messages", "metadata"}
info_techniques = [
f"- {k}: {json.dumps(v, ensure_ascii=False)}" if isinstance(v, (dict, list)) else f"- {k}: {v}"
for k, v in ticket_data.items()
if k not in champs_exclus and v
]
if info_techniques:
texte += "#### INFORMATIONS TECHNIQUES\n" + "\n".join(info_techniques) + "\n\n"
# Fil des échanges client/support
messages = ticket_data.get("messages", [])
if messages:
info += "## CHRONOLOGIE DES ÉCHANGES CLIENT/SUPPORT\n"
texte += "#### ÉCHANGES CLIENT / SUPPORT\n"
for i, msg in enumerate(messages):
# Vérifier que le message est bien un dictionnaire
if not isinstance(msg, dict):
continue
sender = msg.get('from', 'Inconnu')
date = msg.get('date', 'Date inconnue')
content = msg.get('content', '')
# Identifier si c'est client ou support
sender_type = "CLIENT" if "client" in sender.lower() else "SUPPORT" if "support" in sender.lower() else "AUTRE"
# Formater correctement la date si possible
try:
if date != 'Date inconnue':
# Essayer différents formats de date
for date_format in ['%Y-%m-%d %H:%M:%S', '%Y-%m-%d', '%d/%m/%Y']:
try:
date_obj = datetime.strptime(date, date_format)
date = date_obj.strftime('%d/%m/%Y %H:%M')
break
except ValueError:
continue
except Exception:
pass # Garder la date d'origine en cas d'erreur
info += f"### Message {i+1} - [{sender_type}] De: {sender} - Date: {date}\n{content}\n\n"
# Ajouter les métadonnées techniques si présentes
metadata = ticket_data.get('metadata', {})
# Exclure certaines métadonnées internes
for key in ['source_file', 'format']:
if key in metadata:
metadata.pop(key)
if metadata:
info += "## MÉTADONNÉES TECHNIQUES\n"
for key, value in metadata.items():
if isinstance(value, (dict, list)):
value = json.dumps(value, ensure_ascii=False, indent=2)
info += f"- {key}: {value}\n"
info += "\n"
return info
def analyser_depuis_fichier(self, chemin_fichier: str) -> str:
auteur = msg.get("from", "inconnu")
role = "CLIENT" if "client" in auteur.lower() else "SUPPORT" if "support" in auteur.lower() else "AUTRE"
date = self._formater_date(msg.get("date", "inconnue"))
contenu = msg.get("content", "").strip()
if contenu:
texte += f"{i+1}. [{role}] {auteur} ({date})\n{contenu}\n\n"
# Métadonnées utiles
metadata = ticket_data.get("metadata", {})
meta_text = [
f"- {k}: {json.dumps(v, ensure_ascii=False)}" if isinstance(v, (dict, list)) else f"- {k}: {v}"
for k, v in metadata.items()
if k not in {"format", "source_file"} and v
]
if meta_text:
texte += "#### MÉTADONNÉES\n" + "\n".join(meta_text) + "\n"
return texte
def _formater_date(self, date_str: str) -> str:
"""
Analyse un ticket à partir d'un fichier (JSON ou Markdown)
Formate la date en DD/MM/YYYY HH:MM si possible
Args:
chemin_fichier: Chemin vers le fichier à analyser
date_str: Chaîne de caractères représentant une date
Returns:
Résultat de l'analyse
Date formatée ou la chaîne originale si le format n'est pas reconnu
"""
if not date_str:
return "date inconnue"
try:
ticket_data = self.ticket_loader.charger(chemin_fichier)
return self.executer(ticket_data)
except Exception as e:
error_message = f"Erreur lors de l'analyse du fichier {chemin_fichier}: {str(e)}"
logger.error(error_message)
return f"ERREUR: {error_message}"
# Essayer différents formats courants
formats = [
"%Y-%m-%dT%H:%M:%S.%fZ", # Format ISO avec microsecondes et Z
"%Y-%m-%dT%H:%M:%SZ", # Format ISO sans microsecondes avec Z
"%Y-%m-%dT%H:%M:%S", # Format ISO sans Z
"%Y-%m-%d %H:%M:%S", # Format standard
"%d/%m/%Y %H:%M:%S", # Format français
"%d/%m/%Y" # Format date simple
]
for fmt in formats:
try:
dt = datetime.strptime(date_str, fmt)
return dt.strftime("%d/%m/%Y %H:%M")
except ValueError:
continue
# Si aucun format ne correspond, retourner la chaîne originale
return date_str
except Exception:
return date_str
def _get_timestamp(self) -> str:
"""Retourne un timestamp au format YYYYMMDD_HHMMSS"""
return datetime.now().strftime("%Y%m%d_%H%M%S")
"""
Génère un timestamp au format YYYYMMDD_HHMMSS
Returns:
Timestamp formaté
"""
return datetime.now().strftime("%Y%m%d_%H%M%S")

View File

@ -131,44 +131,6 @@ Ton analyse sera utilisée comme élément factuel pour un rapport technique plu
logger.error(f"Erreur lors de la vérification de l'image {image_path}: {str(e)}")
return False
def _encoder_image_base64(self, image_path: str) -> str:
"""
Encode l'image en base64 pour l'inclure directement dans le prompt
Args:
image_path: Chemin vers l'image
Returns:
Chaîne de caractères au format data URI avec l'image encodée en base64
"""
try:
# Ouvrir l'image et la redimensionner si trop grande
with Image.open(image_path) as img:
# Redimensionner l'image si elle est trop grande (max 800x800)
max_size = 800
if img.width > max_size or img.height > max_size:
img.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
# Convertir en RGB si nécessaire (pour les formats comme PNG)
if img.mode != "RGB":
img = img.convert("RGB")
# Sauvegarder l'image en JPEG dans un buffer mémoire
buffer = io.BytesIO()
img.save(buffer, format="JPEG", quality=85)
buffer.seek(0)
# Encoder en base64
img_base64 = base64.b64encode(buffer.read()).decode("utf-8")
# Construire le data URI
data_uri = f"data:image/jpeg;base64,{img_base64}"
return data_uri
except Exception as e:
logger.error(f"Erreur lors de l'encodage de l'image {image_path}: {str(e)}")
return ""
def _generer_prompt_analyse(self, contexte: str, prefix: str = "") -> str:
"""
Génère le prompt d'analyse d'image en utilisant les instructions centralisées
@ -233,20 +195,39 @@ Fournis une analyse STRICTEMENT FACTUELLE de l'image avec les sections suivantes
else:
# Fallback vers la méthode standard avec base64 si interroger_avec_image n'existe pas
logger.warning(f"La méthode interroger_avec_image n'existe pas, utilisation du fallback pour {image_name}")
img_base64 = self._encoder_image_base64(image_path)
if img_base64:
# Utiliser le même générateur de prompt avec l'image en base64
prompt_base64 = self._generer_prompt_analyse(contexte, f"Analyse cette image:\n{img_base64}")
response = self.llm.interroger(prompt_base64)
# Utiliser la méthode _encoder_image_base64 du modèle directement
if hasattr(self.llm, "_encoder_image_base64"):
img_base64 = self.llm._encoder_image_base64(image_path)
if img_base64:
# Utiliser le même générateur de prompt avec l'image en base64
prompt_base64 = self._generer_prompt_analyse(contexte, f"Analyse cette image:\n{img_base64}")
response = self.llm.interroger(prompt_base64)
else:
error_message = "Impossible d'encoder l'image en base64"
logger.error(f"Erreur d'analyse pour {image_name}: {error_message}")
print(f" ERREUR: {error_message}")
# Retourner un résultat d'erreur explicite
return {
"analyse": f"ERREUR: {error_message}. Veuillez vérifier que l'image est dans un format standard.",
"error": True,
"raw_response": "",
"metadata": {
"image_path": image_path,
"image_name": image_name,
"timestamp": self._get_timestamp(),
"error": True
}
}
else:
error_message = "Impossible d'encoder l'image en base64"
error_message = "Le modèle ne supporte pas l'encodage d'images en base64"
logger.error(f"Erreur d'analyse pour {image_name}: {error_message}")
print(f" ERREUR: {error_message}")
# Retourner un résultat d'erreur explicite
return {
"analyse": f"ERREUR: {error_message}. Veuillez vérifier que l'image est dans un format standard.",
"analyse": f"ERREUR: {error_message}. Veuillez utiliser un modèle compatible avec l'analyse d'images.",
"error": True,
"raw_response": "",
"metadata": {

View File

@ -0,0 +1,393 @@
from ..base_agent import BaseAgent
import logging
import os
from typing import Dict, Any, Tuple
from PIL import Image
import base64
import io
logger = logging.getLogger("AgentImageSorter")
class AgentImageSorter(BaseAgent):
"""
Agent pour trier les images et identifier celles qui sont pertinentes.
"""
def __init__(self, llm):
super().__init__("AgentImageSorter", llm)
# Configuration locale de l'agent
self.temperature = 0.2
self.top_p = 0.8
self.max_tokens = 300
# Centralisation des critères de pertinence
self.criteres_pertinence = """
Images PERTINENTES (réponds "oui" ou "pertinent"):
- Captures d'écran de logiciels ou d'interfaces
- logo BRG_LAB
- Référence à "logociel"
- Messages d'erreur
- Configurations système
- Tableaux de bord ou graphiques techniques
- Fenêtres de diagnostic
Images NON PERTINENTES (réponds "non" ou "non pertinent"):
- Photos personnelles
- Images marketing/promotionnelles
- Logos ou images de marque
- Paysages, personnes ou objets non liés à l'informatique
"""
# Centralisation des instructions d'analyse
self.instructions_analyse = """
IMPORTANT: Ne commence JAMAIS ta réponse par "Je ne peux pas directement visualiser l'image".
Si tu ne peux pas analyser l'image, réponds simplement "ERREUR: Impossible d'analyser l'image".
Analyse d'abord ce que montre l'image, puis réponds par "oui"/"pertinent" ou "non"/"non pertinent".
"""
# Construction du système prompt à partir des éléments centralisés
self.system_prompt = f"""Tu es un expert en tri d'images pour le support technique de BRG_Lab pour la société CBAO.
Ta mission est de déterminer si une image est pertinente pour le support technique de logiciels.
{self.criteres_pertinence}
{self.instructions_analyse}"""
# Appliquer la configuration au LLM
self._appliquer_config_locale()
logger.info("AgentImageSorter initialisé")
def _appliquer_config_locale(self) -> None:
"""
Applique la configuration locale au modèle LLM.
"""
# Appliquer le prompt système
if hasattr(self.llm, "prompt_system"):
self.llm.prompt_system = self.system_prompt
# Appliquer les paramètres
if hasattr(self.llm, "configurer"):
params = {
"temperature": self.temperature,
"top_p": self.top_p,
"max_tokens": self.max_tokens
}
self.llm.configurer(**params)
def _verifier_image(self, image_path: str) -> bool:
"""
Vérifie si l'image existe et est accessible
Args:
image_path: Chemin vers l'image
Returns:
True si l'image existe et est accessible, False sinon
"""
try:
# Vérifier que le fichier existe
if not os.path.exists(image_path):
logger.error(f"L'image n'existe pas: {image_path}")
return False
# Vérifier que le fichier est accessible en lecture
if not os.access(image_path, os.R_OK):
logger.error(f"L'image n'est pas accessible en lecture: {image_path}")
return False
# Vérifier que le fichier peut être ouvert comme une image
with Image.open(image_path) as img:
# Vérifier les dimensions de l'image
width, height = img.size
if width <= 0 or height <= 0:
logger.error(f"Dimensions d'image invalides: {width}x{height}")
return False
logger.info(f"Image vérifiée avec succès: {image_path} ({width}x{height})")
return True
except Exception as e:
logger.error(f"Erreur lors de la vérification de l'image {image_path}: {str(e)}")
return False
def _encoder_image_base64(self, image_path: str) -> str:
"""
Encode l'image en base64 pour l'inclure directement dans le prompt
Args:
image_path: Chemin vers l'image
Returns:
Chaîne de caractères au format data URI avec l'image encodée en base64
"""
try:
# Ouvrir l'image et la redimensionner si trop grande
with Image.open(image_path) as img:
# Redimensionner l'image si elle est trop grande (max 800x800)
max_size = 800
if img.width > max_size or img.height > max_size:
img.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
# Convertir en RGB si nécessaire (pour les formats comme PNG)
if img.mode != "RGB":
img = img.convert("RGB")
# Sauvegarder l'image en JPEG dans un buffer mémoire
buffer = io.BytesIO()
img.save(buffer, format="JPEG", quality=85)
buffer.seek(0)
# Encoder en base64
img_base64 = base64.b64encode(buffer.read()).decode("utf-8")
# Construire le data URI
data_uri = f"data:image/jpeg;base64,{img_base64}"
return data_uri
except Exception as e:
logger.error(f"Erreur lors de l'encodage de l'image {image_path}: {str(e)}")
return ""
def _generer_prompt_analyse(self, prefix: str = "", avec_image_base64: bool = False) -> str:
"""
Génère le prompt d'analyse standardisé
Args:
prefix: Préfixe optionnel (pour inclure l'image en base64 par exemple)
avec_image_base64: Indique si le prompt inclut déjà une image en base64
Returns:
Prompt formaté pour l'analyse
"""
return f"""{prefix}
Est-ce une image pertinente pour un ticket de support technique?
Réponds simplement par 'oui' ou 'non' suivi d'une brève explication."""
def executer(self, image_path: str) -> Dict[str, Any]:
"""
Évalue si une image est pertinente pour l'analyse d'un ticket technique
Args:
image_path: Chemin vers l'image à analyser
Returns:
Dictionnaire contenant la décision de pertinence, l'analyse et les métadonnées
"""
image_name = os.path.basename(image_path)
logger.info(f"Évaluation de la pertinence de l'image: {image_name}")
print(f" AgentImageSorter: Évaluation de {image_name}")
# Vérifier que l'image existe et est accessible
if not self._verifier_image(image_path):
error_message = f"L'image n'est pas accessible ou n'est pas valide: {image_name}"
logger.error(error_message)
print(f" ERREUR: {error_message}")
return {
"is_relevant": False,
"reason": f"Erreur d'accès: {error_message}",
"raw_response": "",
"error": True,
"metadata": {
"image_path": image_path,
"image_name": image_name,
"timestamp": self._get_timestamp(),
"error": True
}
}
# Utiliser une référence au fichier image que le modèle peut comprendre
try:
# Préparation du prompt standardisé
prompt = self._generer_prompt_analyse()
# Utiliser la méthode interroger_avec_image au lieu de interroger
if hasattr(self.llm, "interroger_avec_image"):
logger.info(f"Utilisation de la méthode interroger_avec_image pour {image_name}")
response = self.llm.interroger_avec_image(image_path, prompt)
else:
# Fallback vers la méthode standard avec base64 si interroger_avec_image n'existe pas
logger.warning(f"La méthode interroger_avec_image n'existe pas, utilisation du fallback pour {image_name}")
img_base64 = self._encoder_image_base64(image_path)
if img_base64:
prompt_base64 = self._generer_prompt_analyse(f"Analyse cette image:\n{img_base64}", True)
response = self.llm.interroger(prompt_base64)
else:
error_message = "Impossible d'encoder l'image en base64"
logger.error(f"Erreur d'analyse pour {image_name}: {error_message}")
print(f" ERREUR: {error_message}")
return {
"is_relevant": False,
"reason": f"Erreur d'analyse: {error_message}",
"raw_response": "",
"error": True,
"metadata": {
"image_path": image_path,
"image_name": image_name,
"timestamp": self._get_timestamp(),
"error": True
}
}
# Vérifier si la réponse contient des indications que le modèle ne peut pas analyser l'image
error_phrases = [
"je ne peux pas directement visualiser",
"je n'ai pas accès à l'image",
"je ne peux pas voir l'image",
"sans accès direct à l'image",
"je n'ai pas la possibilité de voir",
"je ne peux pas accéder directement",
"erreur: impossible d'analyser l'image"
]
# Vérifier si une des phrases d'erreur est présente dans la réponse
if any(phrase in response.lower() for phrase in error_phrases):
logger.warning(f"Le modèle indique qu'il ne peut pas analyser l'image: {image_name}")
error_message = "Le modèle n'a pas pu analyser l'image correctement"
logger.error(f"Erreur d'analyse pour {image_name}: {error_message}")
print(f" ERREUR: {error_message}")
# Retourner un résultat d'erreur explicite
return {
"is_relevant": False,
"reason": f"Erreur d'analyse: {error_message}",
"raw_response": response,
"error": True,
"metadata": {
"image_path": image_path,
"image_name": image_name,
"timestamp": self._get_timestamp(),
"error": True
}
}
# Analyse de la réponse pour déterminer la pertinence
is_relevant, reason = self._analyser_reponse(response)
logger.info(f"Image {image_name} considérée comme {'pertinente' if is_relevant else 'non pertinente'}")
print(f" Décision: Image {image_name} {'pertinente' if is_relevant else 'non pertinente'}")
# Préparer le résultat
result = {
"is_relevant": is_relevant,
"reason": reason,
"raw_response": response,
"metadata": {
"image_path": image_path,
"image_name": image_name,
"timestamp": self._get_timestamp(),
"model_info": {
"model": getattr(self.llm, "modele", str(type(self.llm))),
"temperature": self.temperature,
"top_p": self.top_p,
"max_tokens": self.max_tokens
}
}
}
# Enregistrer la décision et le raisonnement dans l'historique
self.ajouter_historique("tri_image",
{
"image_path": image_path,
"prompt": prompt
},
{
"response": response,
"is_relevant": is_relevant,
"reason": reason
})
return result
except Exception as e:
logger.error(f"Erreur lors de l'analyse de l'image {image_name}: {str(e)}")
print(f" ERREUR: Impossible d'analyser l'image {image_name}")
# Retourner un résultat par défaut en cas d'erreur
return {
"is_relevant": False, # Par défaut, considérer non pertinent en cas d'erreur
"reason": f"Erreur d'analyse: {str(e)}",
"raw_response": "",
"error": True,
"metadata": {
"image_path": image_path,
"image_name": image_name,
"timestamp": self._get_timestamp(),
"error": True
}
}
def _analyser_reponse(self, response: str) -> Tuple[bool, str]:
"""
Analyse la réponse du LLM pour déterminer la pertinence et extraire le raisonnement
Args:
response: Réponse brute du LLM
Returns:
Tuple (is_relevant, reason) contenant la décision et le raisonnement
"""
# Convertir en minuscule pour faciliter la comparaison
response_lower = response.lower()
# Détection directe des réponses négatives en début de texte
first_line = response_lower.split('\n')[0] if '\n' in response_lower else response_lower[:50]
starts_with_non = first_line.strip().startswith("non") or first_line.strip().startswith("non.")
# Détection explicite d'une réponse négative au début de la réponse
explicit_negative = starts_with_non or any(neg_start in first_line for neg_start in ["non pertinent", "pas pertinent"])
# Détection explicite d'une réponse positive au début de la réponse
explicit_positive = first_line.strip().startswith("oui") or first_line.strip().startswith("pertinent")
# Si une réponse explicite est détectée, l'utiliser directement
if explicit_negative:
is_relevant = False
elif explicit_positive:
is_relevant = True
else:
# Sinon, utiliser l'analyse par mots-clés
# Mots clés positifs forts
positive_keywords = ["oui", "pertinent", "pertinente", "utile", "important", "relevante",
"capture d'écran", "message d'erreur", "interface logicielle",
"configuration", "technique", "diagnostic"]
# Mots clés négatifs forts
negative_keywords = ["non", "pas pertinent", "non pertinente", "inutile", "irrelevant",
"photo personnelle", "marketing", "sans rapport", "hors sujet",
"décorative", "logo"]
# Compter les occurrences de mots clés
positive_count = sum(1 for kw in positive_keywords if kw in response_lower)
negative_count = sum(1 for kw in negative_keywords if kw in response_lower)
# Heuristique de décision basée sur la prépondérance des mots clés
is_relevant = positive_count > negative_count
# Extraire le raisonnement (les dernières phrases de la réponse)
lines = response.split('\n')
reason_lines = []
for line in reversed(lines):
if line.strip():
reason_lines.insert(0, line.strip())
if len(reason_lines) >= 2: # Prendre les 2 dernières lignes non vides
break
reason = " ".join(reason_lines) if reason_lines else "Décision basée sur l'analyse des mots-clés"
# Log détaillé de l'analyse
logger.debug(f"Analyse de la réponse: \n - Réponse brute: {response[:100]}...\n"
f" - Commence par 'non': {starts_with_non}\n"
f" - Détection explicite négative: {explicit_negative}\n"
f" - Détection explicite positive: {explicit_positive}\n"
f" - Décision finale: {'pertinente' if is_relevant else 'non pertinente'}\n"
f" - Raison: {reason}")
return is_relevant, reason
def _get_timestamp(self) -> str:
"""Retourne un timestamp au format YYYYMMDD_HHMMSS"""
from datetime import datetime
return datetime.now().strftime("%Y%m%d_%H%M%S")

View File

@ -3,8 +3,6 @@ import logging
import os
from typing import Dict, Any, Tuple
from PIL import Image
import base64
import io
logger = logging.getLogger("AgentImageSorter")
@ -14,262 +12,104 @@ class AgentImageSorter(BaseAgent):
"""
def __init__(self, llm):
super().__init__("AgentImageSorter", llm)
# Configuration locale de l'agent
# Configuration personnalisable
self.temperature = 0.2
self.top_p = 0.8
self.max_tokens = 300
# Centralisation des critères de pertinence
self.criteres_pertinence = """
Images PERTINENTES (réponds "oui" ou "pertinent"):
- Captures d'écran de logiciels ou d'interfaces
- logo BRG_LAB
- Référence à "logociel"
- Messages d'erreur
- Configurations système
- Tableaux de bord ou graphiques techniques
- Fenêtres de diagnostic
Images NON PERTINENTES (réponds "non" ou "non pertinent"):
- Photos personnelles
- Images marketing/promotionnelles
- Logos ou images de marque
- Paysages, personnes ou objets non liés à l'informatique
"""
self.criteres_pertinence = (
"""
Images PERTINENTES (réponds "oui" ou "pertinent"):
- Captures d'écran de logiciels ou d'interfaces
- logo BRG_LAB
- Référence à "logociel"
- Messages d'erreur
- Configurations système
- Tableaux de bord ou graphiques techniques
- Fenêtres de diagnostic
# Centralisation des instructions d'analyse
self.instructions_analyse = """
IMPORTANT: Ne commence JAMAIS ta réponse par "Je ne peux pas directement visualiser l'image".
Si tu ne peux pas analyser l'image, réponds simplement "ERREUR: Impossible d'analyser l'image".
Images NON PERTINENTES (réponds "non" ou "non pertinent"):
- Photos personnelles
- Images marketing/promotionnelles
- Logos ou images de marque
- Paysages, personnes ou objets non liés à l'informatique
"""
)
Analyse d'abord ce que montre l'image, puis réponds par "oui"/"pertinent" ou "non"/"non pertinent".
"""
self.instructions_analyse = (
"""
IMPORTANT: Ne commence JAMAIS ta réponse par "Je ne peux pas directement visualiser l'image".
Si tu ne peux pas analyser l'image, réponds simplement "ERREUR: Impossible d'analyser l'image".
Analyse d'abord ce que montre l'image, puis réponds par "oui"/"pertinent" ou "non"/"non pertinent".
"""
)
self.system_prompt = (
"""
Tu es un expert en tri d'images pour le support technique de BRG_Lab pour la société CBAO.
Ta mission est de déterminer si une image est pertinente pour le support technique de logiciels.
{criteres}
{instructions}
"""
).format(
criteres=self.criteres_pertinence,
instructions=self.instructions_analyse
)
# Construction du système prompt à partir des éléments centralisés
self.system_prompt = f"""Tu es un expert en tri d'images pour le support technique de BRG_Lab pour la société CBAO.
Ta mission est de déterminer si une image est pertinente pour le support technique de logiciels.
{self.criteres_pertinence}
{self.instructions_analyse}"""
# Appliquer la configuration au LLM
self._appliquer_config_locale()
logger.info("AgentImageSorter initialisé")
def _appliquer_config_locale(self) -> None:
"""
Applique la configuration locale au modèle LLM.
"""
# Appliquer le prompt système
if hasattr(self.llm, "prompt_system"):
self.llm.prompt_system = self.system_prompt
# Appliquer les paramètres
if hasattr(self.llm, "configurer"):
params = {
"temperature": self.temperature,
"top_p": self.top_p,
"max_tokens": self.max_tokens
}
self.llm.configurer(**params)
def _verifier_image(self, image_path: str) -> bool:
"""
Vérifie si l'image existe et est accessible
Args:
image_path: Chemin vers l'image
Returns:
True si l'image existe et est accessible, False sinon
"""
try:
# Vérifier que le fichier existe
if not os.path.exists(image_path):
logger.error(f"L'image n'existe pas: {image_path}")
return False
# Vérifier que le fichier est accessible en lecture
if not os.access(image_path, os.R_OK):
logger.error(f"L'image n'est pas accessible en lecture: {image_path}")
return False
# Vérifier que le fichier peut être ouvert comme une image
with Image.open(image_path) as img:
# Vérifier les dimensions de l'image
width, height = img.size
if width <= 0 or height <= 0:
logger.error(f"Dimensions d'image invalides: {width}x{height}")
return False
logger.info(f"Image vérifiée avec succès: {image_path} ({width}x{height})")
return True
except Exception as e:
logger.error(f"Erreur lors de la vérification de l'image {image_path}: {str(e)}")
return False
def _encoder_image_base64(self, image_path: str) -> str:
"""
Encode l'image en base64 pour l'inclure directement dans le prompt
Args:
image_path: Chemin vers l'image
Returns:
Chaîne de caractères au format data URI avec l'image encodée en base64
"""
try:
# Ouvrir l'image et la redimensionner si trop grande
with Image.open(image_path) as img:
# Redimensionner l'image si elle est trop grande (max 800x800)
max_size = 800
if img.width > max_size or img.height > max_size:
img.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
# Convertir en RGB si nécessaire (pour les formats comme PNG)
if img.mode != "RGB":
img = img.convert("RGB")
# Sauvegarder l'image en JPEG dans un buffer mémoire
buffer = io.BytesIO()
img.save(buffer, format="JPEG", quality=85)
buffer.seek(0)
# Encoder en base64
img_base64 = base64.b64encode(buffer.read()).decode("utf-8")
# Construire le data URI
data_uri = f"data:image/jpeg;base64,{img_base64}"
return data_uri
except Exception as e:
logger.error(f"Erreur lors de l'encodage de l'image {image_path}: {str(e)}")
return ""
def _generer_prompt_analyse(self, prefix: str = "", avec_image_base64: bool = False) -> str:
"""
Génère le prompt d'analyse standardisé
Args:
prefix: Préfixe optionnel (pour inclure l'image en base64 par exemple)
avec_image_base64: Indique si le prompt inclut déjà une image en base64
Returns:
Prompt formaté pour l'analyse
"""
return f"""{prefix}
self.llm.configurer(
temperature=self.temperature,
top_p=self.top_p,
max_tokens=self.max_tokens
)
def _verifier_image(self, image_path: str) -> bool:
try:
if not os.path.exists(image_path) or not os.access(image_path, os.R_OK):
return False
with Image.open(image_path) as img:
width, height = img.size
return width > 0 and height > 0
except Exception as e:
logger.error(f"Vérification impossible pour {image_path}: {e}")
return False
def _generer_prompt_analyse(self, prefix: str = "") -> str:
return f"{prefix}\n\nEst-ce une image pertinente pour un ticket de support technique?\nRéponds simplement par 'oui' ou 'non' suivi d'une brève explication."
def executer(self, image_path: str) -> Dict[str, Any]:
image_name = os.path.basename(image_path)
print(f" AgentImageSorter: Évaluation de {image_name}")
if not self._verifier_image(image_path):
return self._erreur("Erreur d'accès ou image invalide", image_path)
Est-ce une image pertinente pour un ticket de support technique?
Réponds simplement par 'oui' ou 'non' suivi d'une brève explication."""
def executer(self, image_path: str) -> Dict[str, Any]:
"""
Évalue si une image est pertinente pour l'analyse d'un ticket technique
Args:
image_path: Chemin vers l'image à analyser
Returns:
Dictionnaire contenant la décision de pertinence, l'analyse et les métadonnées
"""
image_name = os.path.basename(image_path)
logger.info(f"Évaluation de la pertinence de l'image: {image_name}")
print(f" AgentImageSorter: Évaluation de {image_name}")
# Vérifier que l'image existe et est accessible
if not self._verifier_image(image_path):
error_message = f"L'image n'est pas accessible ou n'est pas valide: {image_name}"
logger.error(error_message)
print(f" ERREUR: {error_message}")
return {
"is_relevant": False,
"reason": f"Erreur d'accès: {error_message}",
"raw_response": "",
"error": True,
"metadata": {
"image_path": image_path,
"image_name": image_name,
"timestamp": self._get_timestamp(),
"error": True
}
}
# Utiliser une référence au fichier image que le modèle peut comprendre
try:
# Préparation du prompt standardisé
prompt = self._generer_prompt_analyse()
# Utiliser la méthode interroger_avec_image au lieu de interroger
if hasattr(self.llm, "interroger_avec_image"):
logger.info(f"Utilisation de la méthode interroger_avec_image pour {image_name}")
response = self.llm.interroger_avec_image(image_path, prompt)
elif hasattr(self.llm, "_encoder_image_base64"):
img_base64 = self.llm._encoder_image_base64(image_path)
prompt = self._generer_prompt_analyse(f"Analyse cette image:\n{img_base64}")
response = self.llm.interroger(prompt)
else:
# Fallback vers la méthode standard avec base64 si interroger_avec_image n'existe pas
logger.warning(f"La méthode interroger_avec_image n'existe pas, utilisation du fallback pour {image_name}")
img_base64 = self._encoder_image_base64(image_path)
if img_base64:
prompt_base64 = self._generer_prompt_analyse(f"Analyse cette image:\n{img_base64}", True)
response = self.llm.interroger(prompt_base64)
else:
error_message = "Impossible d'encoder l'image en base64"
logger.error(f"Erreur d'analyse pour {image_name}: {error_message}")
print(f" ERREUR: {error_message}")
return {
"is_relevant": False,
"reason": f"Erreur d'analyse: {error_message}",
"raw_response": "",
"error": True,
"metadata": {
"image_path": image_path,
"image_name": image_name,
"timestamp": self._get_timestamp(),
"error": True
}
}
# Vérifier si la réponse contient des indications que le modèle ne peut pas analyser l'image
error_phrases = [
"je ne peux pas directement visualiser",
"je n'ai pas accès à l'image",
"je ne peux pas voir l'image",
"sans accès direct à l'image",
"je n'ai pas la possibilité de voir",
"je ne peux pas accéder directement",
"erreur: impossible d'analyser l'image"
]
# Vérifier si une des phrases d'erreur est présente dans la réponse
if any(phrase in response.lower() for phrase in error_phrases):
logger.warning(f"Le modèle indique qu'il ne peut pas analyser l'image: {image_name}")
error_message = "Le modèle n'a pas pu analyser l'image correctement"
logger.error(f"Erreur d'analyse pour {image_name}: {error_message}")
print(f" ERREUR: {error_message}")
# Retourner un résultat d'erreur explicite
return {
"is_relevant": False,
"reason": f"Erreur d'analyse: {error_message}",
"raw_response": response,
"error": True,
"metadata": {
"image_path": image_path,
"image_name": image_name,
"timestamp": self._get_timestamp(),
"error": True
}
}
# Analyse de la réponse pour déterminer la pertinence
return self._erreur("Le modèle ne supporte pas les images", image_path)
if any(err in response.lower() for err in [
"je ne peux pas", "je n'ai pas accès", "impossible d'analyser"]):
return self._erreur("Réponse du modèle invalide", image_path, raw=response)
is_relevant, reason = self._analyser_reponse(response)
logger.info(f"Image {image_name} considérée comme {'pertinente' if is_relevant else 'non pertinente'}")
print(f" Décision: Image {image_name} {'pertinente' if is_relevant else 'non pertinente'}")
# Préparer le résultat
result = {
"is_relevant": is_relevant,
"reason": reason,
@ -280,114 +120,45 @@ Réponds simplement par 'oui' ou 'non' suivi d'une brève explication."""
"timestamp": self._get_timestamp(),
"model_info": {
"model": getattr(self.llm, "modele", str(type(self.llm))),
"temperature": self.temperature,
"top_p": self.top_p,
"max_tokens": self.max_tokens
}
**getattr(self.llm, "params", {})
},
"source_agent": self.nom
}
}
# Enregistrer la décision et le raisonnement dans l'historique
self.ajouter_historique("tri_image",
{
"image_path": image_path,
"prompt": prompt
},
{
"response": response,
"is_relevant": is_relevant,
"reason": reason
})
self.ajouter_historique("tri_image", {"image_path": image_path, "prompt": prompt}, result)
return result
except Exception as e:
logger.error(f"Erreur lors de l'analyse de l'image {image_name}: {str(e)}")
print(f" ERREUR: Impossible d'analyser l'image {image_name}")
# Retourner un résultat par défaut en cas d'erreur
return {
"is_relevant": False, # Par défaut, considérer non pertinent en cas d'erreur
"reason": f"Erreur d'analyse: {str(e)}",
"raw_response": "",
"error": True,
"metadata": {
"image_path": image_path,
"image_name": image_name,
"timestamp": self._get_timestamp(),
"error": True
}
}
return self._erreur(str(e), image_path)
def _analyser_reponse(self, response: str) -> Tuple[bool, str]:
"""
Analyse la réponse du LLM pour déterminer la pertinence et extraire le raisonnement
Args:
response: Réponse brute du LLM
Returns:
Tuple (is_relevant, reason) contenant la décision et le raisonnement
"""
# Convertir en minuscule pour faciliter la comparaison
response_lower = response.lower()
# Détection directe des réponses négatives en début de texte
first_line = response_lower.split('\n')[0] if '\n' in response_lower else response_lower[:50]
starts_with_non = first_line.strip().startswith("non") or first_line.strip().startswith("non.")
# Détection explicite d'une réponse négative au début de la réponse
explicit_negative = starts_with_non or any(neg_start in first_line for neg_start in ["non pertinent", "pas pertinent"])
# Détection explicite d'une réponse positive au début de la réponse
explicit_positive = first_line.strip().startswith("oui") or first_line.strip().startswith("pertinent")
# Si une réponse explicite est détectée, l'utiliser directement
if explicit_negative:
is_relevant = False
elif explicit_positive:
is_relevant = True
else:
# Sinon, utiliser l'analyse par mots-clés
# Mots clés positifs forts
positive_keywords = ["oui", "pertinent", "pertinente", "utile", "important", "relevante",
"capture d'écran", "message d'erreur", "interface logicielle",
"configuration", "technique", "diagnostic"]
# Mots clés négatifs forts
negative_keywords = ["non", "pas pertinent", "non pertinente", "inutile", "irrelevant",
"photo personnelle", "marketing", "sans rapport", "hors sujet",
"décorative", "logo"]
# Compter les occurrences de mots clés
positive_count = sum(1 for kw in positive_keywords if kw in response_lower)
negative_count = sum(1 for kw in negative_keywords if kw in response_lower)
# Heuristique de décision basée sur la prépondérance des mots clés
is_relevant = positive_count > negative_count
# Extraire le raisonnement (les dernières phrases de la réponse)
lines = response.split('\n')
reason_lines = []
for line in reversed(lines):
if line.strip():
reason_lines.insert(0, line.strip())
if len(reason_lines) >= 2: # Prendre les 2 dernières lignes non vides
break
reason = " ".join(reason_lines) if reason_lines else "Décision basée sur l'analyse des mots-clés"
# Log détaillé de l'analyse
logger.debug(f"Analyse de la réponse: \n - Réponse brute: {response[:100]}...\n"
f" - Commence par 'non': {starts_with_non}\n"
f" - Détection explicite négative: {explicit_negative}\n"
f" - Détection explicite positive: {explicit_positive}\n"
f" - Décision finale: {'pertinente' if is_relevant else 'non pertinente'}\n"
f" - Raison: {reason}")
return is_relevant, reason
r = response.lower()
first_line = r.split('\n')[0] if '\n' in r else r[:50].strip()
if first_line.startswith("non") or "non pertinent" in first_line:
return False, response.strip()
if first_line.startswith("oui") or "pertinent" in first_line:
return True, response.strip()
pos_keywords = ["pertinent", "utile", "important", "diagnostic"]
neg_keywords = ["inutile", "photo", "hors sujet", "marketing", "non pertinent"]
score = sum(kw in r for kw in pos_keywords) - sum(kw in r for kw in neg_keywords)
return score > 0, response.strip()
def _erreur(self, message: str, path: str, raw: str = "") -> Dict[str, Any]:
return {
"is_relevant": False,
"reason": message,
"raw_response": raw,
"error": True,
"metadata": {
"image_path": path,
"image_name": os.path.basename(path),
"timestamp": self._get_timestamp(),
"error": True,
"source_agent": self.nom
}
}
def _get_timestamp(self) -> str:
"""Retourne un timestamp au format YYYYMMDD_HHMMSS"""
from datetime import datetime
return datetime.now().strftime("%Y%m%d_%H%M%S")
return datetime.now().strftime("%Y%m%d_%H%M%S")

View File

@ -16,7 +16,9 @@ class BaseLLM(abc.ABC):
"max_tokens": 4000,
"presence_penalty": 0,
"frequency_penalty": 0,
"stop": []
"stop": [],
"stream":False,
"n":1
}
self.dureeTraitement: timedelta = timedelta()

477
orchestrator.bak Normal file
View File

@ -0,0 +1,477 @@
import os
import json
import logging
import time
import traceback
from typing import List, Dict, Any, Optional, Union, Mapping, cast
from agents.base_agent import BaseAgent
from loaders.ticket_data_loader import TicketDataLoader
from agents.utils.report_formatter import generer_rapport_markdown
# Configuration du logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s',
filename='orchestrator.log', filemode='w')
logger = logging.getLogger("Orchestrator")
class Orchestrator:
"""
Orchestrateur pour l'analyse de tickets et la génération de rapports.
Stratégie de gestion des formats:
- JSON est le format principal pour le traitement des données et l'analyse
- Markdown est utilisé uniquement comme format de présentation finale
- Les agents LLM travaillent principalement avec le format JSON
- La conversion JSON->Markdown se fait uniquement à la fin du processus pour la présentation
Cette approche permet de:
1. Simplifier le code des agents
2. Réduire les redondances et incohérences entre formats
3. Améliorer la performance des agents LLM avec un format plus structuré
4. Faciliter la maintenance et l'évolution du système
"""
def __init__(self,
output_dir: str = "output/",
ticket_agent: Optional[BaseAgent] = None,
image_sorter: Optional[BaseAgent] = None,
image_analyser: Optional[BaseAgent] = None,
report_generator: Optional[BaseAgent] = None):
self.output_dir = output_dir
# Assignation directe des agents
self.ticket_agent = ticket_agent
self.image_sorter = image_sorter
self.image_analyser = image_analyser
self.report_generator = report_generator
# Initialisation du loader de données de ticket
self.ticket_loader = TicketDataLoader()
# Collecter et enregistrer les informations détaillées sur les agents
agents_info = self._collecter_info_agents()
logger.info(f"Orchestrator initialisé avec output_dir: {output_dir}")
logger.info(f"Agents disponibles: TicketAgent={ticket_agent is not None}, ImageSorter={image_sorter is not None}, ImageAnalyser={image_analyser is not None}, ReportGenerator={report_generator is not None}")
logger.info(f"Configuration des agents: {json.dumps(agents_info, indent=2)}")
def _collecter_info_agents(self) -> Dict[str, Dict[str, Any]]:
"""
Collecte des informations détaillées sur les agents configurés
"""
agents_info = {}
# Information sur l'agent Ticket
if self.ticket_agent:
agents_info["ticket_agent"] = self._get_agent_info(self.ticket_agent)
# Information sur l'agent Image Sorter
if self.image_sorter:
agents_info["image_sorter"] = self._get_agent_info(self.image_sorter)
# Information sur l'agent Image Analyser
if self.image_analyser:
agents_info["image_analyser"] = self._get_agent_info(self.image_analyser)
# Information sur l'agent Report Generator
if self.report_generator:
agents_info["report_generator"] = self._get_agent_info(self.report_generator)
return agents_info
def detecter_tickets(self) -> List[str]:
"""Détecte tous les tickets disponibles dans le répertoire de sortie"""
logger.info(f"Recherche de tickets dans: {self.output_dir}")
tickets = []
if not os.path.exists(self.output_dir):
logger.warning(f"Le répertoire de sortie {self.output_dir} n'existe pas")
print(f"ERREUR: Le répertoire {self.output_dir} n'existe pas")
return tickets
for ticket_dir in os.listdir(self.output_dir):
ticket_path = os.path.join(self.output_dir, ticket_dir)
if os.path.isdir(ticket_path) and ticket_dir.startswith("ticket_"):
tickets.append(ticket_dir)
return tickets
def trouver_rapport(self, extraction_path: str, ticket_id: str) -> Dict[str, Optional[str]]:
"""
Cherche les rapports disponibles (JSON et/ou MD) pour un ticket
Args:
extraction_path: Chemin vers l'extraction
ticket_id: ID du ticket
Returns:
Dictionnaire avec {"json": chemin_json, "markdown": chemin_md}
"""
# Utiliser la méthode du TicketDataLoader pour trouver les fichiers
result = self.ticket_loader.trouver_ticket(extraction_path, ticket_id)
# S'assurer que nous avons un dictionnaire avec la structure correcte
rapports: Dict[str, Optional[str]] = {"json": None, "markdown": None} if result is None else result
# Si on a un JSON mais pas de Markdown, générer le Markdown à partir du JSON
json_path = rapports.get("json")
if json_path and not rapports.get("markdown"):
logger.info(f"Rapport JSON trouvé sans Markdown correspondant, génération du Markdown: {json_path}")
md_path = generer_rapport_markdown(json_path, True)
if md_path:
rapports["markdown"] = md_path
logger.info(f"Markdown généré avec succès: {md_path}")
else:
logger.warning(f"Erreur lors de la génération du Markdown")
return rapports
def executer(self, ticket_specifique: Optional[str] = None):
"""
Exécute l'orchestrateur soit sur un ticket spécifique, soit sur tous les tickets
Args:
ticket_specifique: Code du ticket spécifique à traiter (optionnel)
"""
start_time = time.time()
# Obtenir la liste des tickets
if ticket_specifique:
# Chercher le ticket spécifique
ticket_path = os.path.join(self.output_dir, f"ticket_{ticket_specifique}")
if os.path.exists(ticket_path):
ticket_dirs = [ticket_path]
logger.info(f"Ticket spécifique à traiter: {ticket_specifique}")
print(f"Ticket spécifique à traiter: {ticket_specifique}")
else:
logger.error(f"Le ticket {ticket_specifique} n'existe pas")
print(f"ERREUR: Le ticket {ticket_specifique} n'existe pas")
return
else:
# Lister tous les tickets
ticket_dirs = [os.path.join(self.output_dir, d) for d in self.detecter_tickets()]
logger.info(f"Tickets à traiter: {len(ticket_dirs)}")
if not ticket_dirs:
logger.warning("Aucun ticket trouvé dans le répertoire de sortie")
print("Aucun ticket trouvé dans le répertoire de sortie")
return
# Un seul log de début d'exécution
logger.info("Début de l'exécution de l'orchestrateur")
print("Début de l'exécution de l'orchestrateur")
# Traitement des tickets
for ticket_dir in ticket_dirs:
try:
self.traiter_ticket(ticket_dir)
except Exception as e:
logger.error(f"Erreur lors du traitement du ticket {ticket_dir}: {str(e)}")
print(f"Erreur lors du traitement du ticket {ticket_dir}: {str(e)}")
traceback.print_exc()
# Calcul de la durée d'exécution
duration = time.time() - start_time
logger.info(f"Fin de l'exécution de l'orchestrateur (durée: {duration:.2f} secondes)")
print(f"Fin de l'exécution de l'orchestrateur (durée: {duration:.2f} secondes)")
def traiter_ticket(self, ticket_path: str) -> bool:
"""Traite un ticket spécifique et retourne True si le traitement a réussi"""
logger.info(f"Début du traitement du ticket: {ticket_path}")
print(f"\nTraitement du ticket: {os.path.basename(ticket_path)}")
success = False
extractions_trouvees = False
if not os.path.exists(ticket_path):
logger.error(f"Le chemin du ticket n'existe pas: {ticket_path}")
print(f"ERREUR: Le chemin du ticket n'existe pas: {ticket_path}")
return False
ticket_id = os.path.basename(ticket_path).replace("ticket_", "")
for extraction in os.listdir(ticket_path):
extraction_path = os.path.join(ticket_path, extraction)
if os.path.isdir(extraction_path):
extractions_trouvees = True
logger.info(f"Traitement de l'extraction: {extraction}")
print(f" Traitement de l'extraction: {extraction}")
# Recherche des rapports (JSON et MD) dans différents emplacements
rapports = self.trouver_rapport(extraction_path, ticket_id)
# Dossier des pièces jointes
attachments_dir = os.path.join(extraction_path, "attachments")
# Dossier pour les rapports générés
rapports_dir = os.path.join(extraction_path, f"{ticket_id}_rapports")
os.makedirs(rapports_dir, exist_ok=True)
# Préparer les données du ticket à partir des rapports trouvés
ticket_data = self._preparer_donnees_ticket(rapports, ticket_id)
if ticket_data:
success = True
logger.info(f"Données du ticket chargées avec succès")
print(f" Données du ticket chargées")
# Traitement avec l'agent Ticket
if self.ticket_agent:
logger.info("Exécution de l'agent Ticket")
print(" Analyse du ticket en cours...")
# Log détaillé sur l'agent Ticket
agent_info = self._get_agent_info(self.ticket_agent)
logger.info(f"Agent Ticket: {json.dumps(agent_info, indent=2)}")
ticket_analysis = self.ticket_agent.executer(ticket_data)
logger.info("Analyse du ticket terminée")
print(f" Analyse du ticket terminée: {len(ticket_analysis) if ticket_analysis else 0} caractères")
else:
logger.warning("Agent Ticket non disponible")
ticket_analysis = None
print(" Agent Ticket non disponible, analyse ignorée")
# Traitement des images
relevant_images = []
images_analyses = {}
images_count = 0
if os.path.exists(attachments_dir):
logger.info(f"Vérification des pièces jointes dans: {attachments_dir}")
print(f" Vérification des pièces jointes...")
# Log détaillé sur l'agent Image Sorter
if self.image_sorter:
agent_info = self._get_agent_info(self.image_sorter)
logger.info(f"Agent Image Sorter: {json.dumps(agent_info, indent=2)}")
# Compter le nombre d'images
images = [f for f in os.listdir(attachments_dir)
if f.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif'))]
images_count = len(images)
# Tri des images
for img in images:
img_path = os.path.join(attachments_dir, img)
if self.image_sorter:
logger.info(f"Évaluation de la pertinence de l'image: {img}")
print(f" Évaluation de l'image: {img}")
sorting_result = self.image_sorter.executer(img_path)
is_relevant = sorting_result.get("is_relevant", False)
reason = sorting_result.get("reason", "")
# Log détaillé du résultat
if is_relevant:
logger.info(f"Image {img} considérée comme pertinente")
else:
logger.info(f"Image {img} considérée comme non pertinente")
# Ajouter les métadonnées de tri à la liste des analyses
images_analyses[img_path] = {
"sorting": sorting_result,
"analysis": None # Sera rempli plus tard si pertinent
}
if is_relevant:
logger.info(f"Image pertinente identifiée: {img} ({reason})")
print(f" => Pertinente: {reason}")
relevant_images.append(img_path)
else:
logger.info(f"Image non pertinente: {img} ({reason})")
print(f" => Non pertinente: {reason}")
else:
logger.warning("Image Sorter non disponible")
# Si pas de tri, considérer toutes les images comme pertinentes
relevant_images.append(img_path)
images_analyses[img_path] = {
"sorting": {"is_relevant": True, "reason": "Auto-sélectionné (pas de tri)"},
"analysis": None
}
print(f" => Auto-sélectionné (pas de tri)")
logger.info(f"Images analysées: {images_count}, Images pertinentes: {len(relevant_images)}")
print(f" Images analysées: {images_count}, Images pertinentes: {len(relevant_images)}")
else:
logger.warning(f"Répertoire des pièces jointes non trouvé: {attachments_dir}")
print(f" Répertoire des pièces jointes non trouvé")
# Analyse approfondie des images pertinentes
if relevant_images and self.image_analyser:
agent_info = self._get_agent_info(self.image_analyser)
logger.info(f"Agent Image Analyser: {json.dumps(agent_info, indent=2)}")
# S'assurer que l'analyse du ticket est disponible comme contexte
contexte_ticket = ticket_analysis if ticket_analysis else "Aucune analyse de ticket disponible"
# Analyse de chaque image pertinente
for image_path in relevant_images:
image_name = os.path.basename(image_path)
logger.info(f"Analyse approfondie de l'image: {image_name}")
print(f" Analyse approfondie de l'image: {image_name}")
# Appeler l'analyseur d'images avec le contexte du ticket
analysis_result = self.image_analyser.executer(image_path, contexte=contexte_ticket)
if images_analyses[image_path]:
images_analyses[image_path]["analysis"] = analysis_result
logger.info(f"Analyse complétée pour {image_name}")
# Préparer les données pour le rapport final
rapport_data = {
"ticket_data": ticket_data,
"ticket_id": ticket_id,
"ticket_analyse": ticket_analysis,
"analyse_images": images_analyses,
"metadata": {
"timestamp_debut": self._get_timestamp(),
"ticket_id": ticket_id,
"images_analysees": images_count,
"images_pertinentes": len(relevant_images)
}
}
# Génération du rapport final
if self.report_generator:
logger.info("Génération du rapport final")
print(" Génération du rapport final")
# Log détaillé sur l'agent Report Generator
agent_info = self._get_agent_info(self.report_generator)
logger.info(f"Agent Report Generator: {json.dumps(agent_info, indent=2)}")
# Créer le répertoire pour le rapport dans reports/
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__)))
reports_root_dir = os.path.join(project_root, 'reports')
ticket_reports_dir = os.path.join(reports_root_dir, ticket_id)
# Créer le sous-répertoire pour le modèle spécifique
model_name = getattr(self.report_generator.llm, "modele", str(type(self.report_generator.llm)))
model_reports_dir = os.path.join(ticket_reports_dir, model_name)
os.makedirs(model_reports_dir, exist_ok=True)
# Générer le rapport
json_path, md_path = self.report_generator.executer(rapport_data, model_reports_dir)
if json_path:
logger.info(f"Rapport JSON généré à: {json_path}")
print(f" Rapport JSON généré avec succès: {os.path.basename(json_path)}")
# Utiliser directement le rapport Markdown généré par l'agent
if md_path:
logger.info(f"Rapport Markdown généré à: {md_path}")
print(f" Rapport Markdown généré avec succès: {os.path.basename(md_path)}")
else:
logger.warning("Report Generator non disponible")
print(" Report Generator non disponible, génération de rapport ignorée")
print(f"Traitement du ticket {os.path.basename(ticket_path)} terminé avec succès.\n")
logger.info(f"Traitement du ticket {ticket_path} terminé avec succès.")
else:
logger.warning(f"Aucune donnée de ticket trouvée pour: {ticket_id}")
print(f" ERREUR: Aucune donnée de ticket trouvée pour {ticket_id}")
if not extractions_trouvees:
logger.warning(f"Aucune extraction trouvée dans le ticket: {ticket_path}")
print(f" ERREUR: Aucune extraction trouvée dans le ticket")
return success
def _preparer_donnees_ticket(self, rapports: Dict[str, Optional[str]], ticket_id: str) -> Optional[Dict]:
"""
Prépare les données du ticket à partir des rapports trouvés (JSON et/ou MD)
Args:
rapports: Dictionnaire avec les chemins des rapports JSON et MD
ticket_id: ID du ticket
Returns:
Dictionnaire avec les données du ticket, ou None si aucun rapport n'est trouvé
"""
ticket_data = None
# Si aucun rapport n'est trouvé
if not rapports or (not rapports.get("json") and not rapports.get("markdown")):
logger.warning(f"Aucun rapport trouvé pour le ticket {ticket_id}")
return None
# Privilégier le format JSON (format principal)
if rapports.get("json") and rapports["json"] is not None:
try:
ticket_data = self.ticket_loader.charger(rapports["json"])
logger.info(f"Données JSON chargées depuis: {rapports['json']}")
print(f" Rapport JSON chargé: {os.path.basename(rapports['json'])}")
# Ajouter une métadonnée sur le format source
if ticket_data and "metadata" not in ticket_data:
ticket_data["metadata"] = {}
if ticket_data:
ticket_data["metadata"]["format_source"] = "json"
except Exception as e:
logger.error(f"Erreur lors du chargement du JSON: {e}")
print(f" ERREUR: Impossible de charger le fichier JSON: {e}")
# Fallback sur le Markdown uniquement si JSON non disponible
if not ticket_data and rapports.get("markdown") and rapports["markdown"] is not None:
try:
# Utiliser le loader pour charger les données depuis le Markdown
ticket_data = self.ticket_loader.charger(rapports["markdown"])
logger.info(f"Données Markdown chargées depuis: {rapports['markdown']} (fallback)")
print(f" Rapport Markdown chargé (fallback): {os.path.basename(rapports['markdown'])}")
# Ajouter une métadonnée sur le format source
if ticket_data and "metadata" not in ticket_data:
ticket_data["metadata"] = {}
if ticket_data:
ticket_data["metadata"]["format_source"] = "markdown"
except Exception as e:
logger.error(f"Erreur lors du chargement du Markdown: {e}")
print(f" ERREUR: Impossible de charger le fichier Markdown: {e}")
# Assurer que l'ID du ticket est correct
if ticket_data:
ticket_data["code"] = ticket_id
return ticket_data
def _get_timestamp(self) -> str:
"""Retourne un timestamp au format YYYYMMDD_HHMMSS"""
from datetime import datetime
return datetime.now().strftime("%Y%m%d_%H%M%S")
def _get_agent_info(self, agent: Optional[BaseAgent]) -> Dict:
"""
Récupère les informations détaillées sur un agent.
Args:
agent: L'agent dont on veut récupérer les informations
Returns:
Dictionnaire contenant les informations de l'agent
"""
if not agent:
return {"status": "non configuré"}
# Récupérer les informations du modèle
model_info = {
"nom": agent.nom,
"model": getattr(agent.llm, "modele", str(type(agent.llm))),
}
# Ajouter les paramètres de configuration s'ils sont disponibles directement dans l'agent
# Utiliser getattr avec une valeur par défaut pour éviter les erreurs
model_info["temperature"] = getattr(agent, "temperature", None)
model_info["top_p"] = getattr(agent, "top_p", None)
model_info["max_tokens"] = getattr(agent, "max_tokens", None)
# Ajouter le prompt système s'il est disponible
if hasattr(agent, "system_prompt"):
prompt_preview = getattr(agent, "system_prompt", "")
# Tronquer le prompt s'il est trop long
if prompt_preview and len(prompt_preview) > 200:
prompt_preview = prompt_preview[:200] + "..."
model_info["system_prompt_preview"] = prompt_preview
# Supprimer les valeurs None
model_info = {k: v for k, v in model_info.items() if v is not None}
return model_info

View File

@ -7,6 +7,7 @@ from typing import List, Dict, Any, Optional, Union, Mapping, cast
from agents.base_agent import BaseAgent
from loaders.ticket_data_loader import TicketDataLoader
from agents.utils.report_formatter import generer_rapport_markdown
from utils.image_dedup import filtrer_images_uniques
# Configuration du logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s',
@ -246,8 +247,10 @@ class Orchestrator:
logger.info(f"Agent Image Sorter: {json.dumps(agent_info, indent=2)}")
# Compter le nombre d'images
images = [f for f in os.listdir(attachments_dir)
if f.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif'))]
images = [f for f in os.listdir(attachments_dir) if f.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif'))]
image_paths = [os.path.join(attachments_dir, img) for img in images]
image_paths_uniques = filtrer_images_uniques(image_paths)
images = [os.path.basename(p) for p in image_paths_uniques]
images_count = len(images)
# Tri des images

View File

@ -0,0 +1,92 @@
{
"timestamp": "20250416_151115",
"batch_dir": "output",
"search_criteria": {
"domain": [
[
"project_id",
"=",
3
],
[
"stage_id",
"=",
8
]
],
"limit": 10,
"offset": 0
},
"processed_tickets": [],
"skipped_tickets": [
{
"code": "T11181",
"id": 11160,
"name": "N'arrive pas à dupliquer un echantillon",
"reason": "already_extracted"
},
{
"code": "T11178",
"id": 11157,
"name": "Bug BRG-LAB",
"reason": "already_extracted"
},
{
"code": "T11163",
"id": 11142,
"name": "Essai de plaque LCPC MEI + Divers ",
"reason": "already_extracted"
},
{
"code": "T11146",
"id": 11125,
"name": "formulation",
"reason": "already_extracted"
},
{
"code": "T11143",
"id": 11122,
"name": "BRGLAB - Essai inaccessible",
"reason": "already_extracted"
},
{
"code": "T11140",
"id": 11119,
"name": "Impossible de prendre en compte un prix dans une formulation",
"reason": "already_extracted"
},
{
"code": "T11132",
"id": 11111,
"name": "Re: brg-lab.com",
"reason": "already_extracted"
},
{
"code": "T11130",
"id": 11109,
"name": "sondages dans le désordre",
"reason": "already_extracted"
},
{
"code": "T11127",
"id": 11106,
"name": "ET2025-E-0114 - Impossible d'afficher l'essais",
"reason": "already_extracted"
},
{
"code": "T11126",
"id": 11105,
"name": "Message d'erreur sur essais au format tableur FTP",
"reason": "already_extracted"
}
],
"failed_tickets": [],
"excluded_tickets": [],
"stats": {
"total_found": 10,
"processed": 0,
"skipped": 10,
"failed": 0,
"excluded_by_tag": 0
}
}

View File

@ -0,0 +1,112 @@
{
"timestamp": "20250416_151200",
"batch_dir": "output",
"search_criteria": {
"domain": [
[
"project_id",
"=",
3
],
[
"stage_id",
"=",
8
]
],
"limit": 10,
"offset": 30
},
"processed_tickets": [
{
"code": "T11093",
"id": 11072,
"name": "Re: [T9294] - Fiche CE - Catégories manquant pour teneur en sulfate soluble dans l'eau (SS)",
"output_dir": "output/ticket_T11093/T11093_20250416_151200",
"messages_count": 5,
"attachments_count": 3
},
{
"code": "T11091",
"id": 11070,
"name": "Norme 1097-1 ",
"output_dir": "output/ticket_T11091/T11091_20250416_151202",
"messages_count": 5,
"attachments_count": 0
},
{
"code": "T11089",
"id": 11068,
"name": "Problème création feuille paillasse béton",
"output_dir": "output/ticket_T11089/T11089_20250416_151202",
"messages_count": 10,
"attachments_count": 12
},
{
"code": "T11088",
"id": 11067,
"name": "BUG mise à jour",
"output_dir": "output/ticket_T11088/T11088_20250416_151205",
"messages_count": 5,
"attachments_count": 4
},
{
"code": "T11087",
"id": 11066,
"name": "erreur fatale essai aplatissement",
"output_dir": "output/ticket_T11087/T11087_20250416_151207",
"messages_count": 5,
"attachments_count": 2
},
{
"code": "T11086",
"id": 11065,
"name": "Erreur fatale essai VBS",
"output_dir": "output/ticket_T11086/T11086_20250416_151208",
"messages_count": 5,
"attachments_count": 4
},
{
"code": "T11085",
"id": 11064,
"name": "cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN",
"output_dir": "output/ticket_T11085/T11085_20250416_151209",
"messages_count": 4,
"attachments_count": 2
},
{
"code": "T11084",
"id": 11063,
"name": "Site bloqué après MAJ",
"output_dir": "output/ticket_T11084/T11084_20250416_151209",
"messages_count": 4,
"attachments_count": 0
},
{
"code": "T11083",
"id": 11062,
"name": "Site bloqué après MAJ",
"output_dir": "output/ticket_T11083/T11083_20250416_151210",
"messages_count": 2,
"attachments_count": 0
},
{
"code": "T11082",
"id": 11061,
"name": "MISE A JOUR DE LA PLATEFORME",
"output_dir": "output/ticket_T11082/T11082_20250416_151210",
"messages_count": 5,
"attachments_count": 2
}
],
"skipped_tickets": [],
"failed_tickets": [],
"excluded_tickets": [],
"stats": {
"total_found": 10,
"processed": 10,
"skipped": 0,
"failed": 0,
"excluded_by_tag": 0
}
}

View File

@ -1,24 +1,34 @@
{
"ticket_codes": [
"T11117",
"T11112",
"T11132",
"T11113",
"T11119",
"T11125",
"T11130",
"T11126",
"T11143",
"T11127",
"T11114",
"T11082",
"T11118",
"T11123",
"T11181",
"T11122",
"T11178",
"T11163",
"T11115",
"T11113",
"T11132",
"T11140",
"T11146"
"T11181",
"T11086",
"T11114",
"T11122",
"T11126",
"T11089",
"T11143",
"T11163",
"T11085",
"T11130",
"T11084",
"T11087",
"T11146",
"T11091",
"T11127",
"T11115",
"T11093",
"T11088",
"T11178",
"T11119",
"T11083",
"T11123",
"T11112"
]
}

View File

@ -0,0 +1,34 @@
{
"id": "11061",
"code": "T11082",
"name": "MISE A JOUR DE LA PLATEFORME",
"description": "*Contenu non extractible*",
"project_name": "Demandes",
"stage_name": "Clôturé",
"user_id": "",
"partner_id_email_from": "GEOLABO, Contact - GEOLABO <contact@geolabo.fr>",
"create_date": "19/03/2025 10:41:36",
"write_date_last_modification": "03/04/2025 07:51:14",
"date_deadline": "03/04/2025 00:00:00",
"messages": [
{
"author_id": "GEOLABO",
"date": "19/03/2025 10:40:30",
"message_type": "E-mail",
"subject": "MISE A JOUR DE LA PLATEFORME",
"id": "227893",
"content": "Bonjour,\nLa plateforme est en mise ce matin depuis un moment, pourra ton accéder à cette dernière en début daprès midi ?\nMerci davance\nGRANGIER Aurore\nTéléphone:04.92.76.65.93\nTélécopie:09.67.22.65.93\nAdresse Email :\ncontact@geolabo.fr\nadresse postale:\n172 Chemin des Grands Jardins\n04220 SAINTE TULLE\n\n- image001.jpg (image/jpeg) [ID: 144863]\n\n---\n\n"
},
{
"author_id": "Romuald GRUSON",
"date": "19/03/2025 10:45:56",
"message_type": "E-mail",
"subject": "Re: [T11082] - MISE A JOUR DE LA PLATEFORME",
"id": "227897",
"content": "Bonjour\n,\nNous relançons la mise à jour dès à présent. Votre plateforme sera de nouveau disponible en début d'après-midi.\nJe reste à votre entière disposition pour toute information complémentaire.\nCordialement,\n---\nSupport technique\n\n---\n"
}
],
"date_d'extraction": "16/04/2025 15:12:11",
"répertoire": "output/ticket_T11082/T11082_20250416_151210",
"messages_raw_reference": "output/ticket_T11082/T11082_20250416_151210/messages_raw.json"
}

View File

@ -0,0 +1,64 @@
# Ticket T11082: MISE A JOUR DE LA PLATEFORME
## Informations du ticket
- **id**: 11061
- **code**: T11082
- **name**: MISE A JOUR DE LA PLATEFORME
- **project_name**: Demandes
- **stage_name**: Clôturé
- **user_id**:
- **partner_id/email_from**: GEOLABO, Contact - GEOLABO <contact@geolabo.fr>
- **create_date**: 19/03/2025 10:41:36
- **write_date/last modification**: 03/04/2025 07:51:14
- **date_deadline**: 03/04/2025 00:00:00
- **description**:
*Contenu non extractible*
## Messages
### Message 1
**author_id**: GEOLABO
**date**: 19/03/2025 10:40:30
**message_type**: E-mail
**subject**: MISE A JOUR DE LA PLATEFORME
**id**: 227893
Bonjour,
La plateforme est en mise ce matin depuis un moment, pourra ton accéder à cette dernière en début daprès midi ?
Merci davance
GRANGIER Aurore
Téléphone:04.92.76.65.93
Télécopie:09.67.22.65.93
Adresse Email :
contact@geolabo.fr
adresse postale:
172 Chemin des Grands Jardins
04220 SAINTE TULLE
**attachment_ids**:
- image001.jpg (image/jpeg) [ID: 144863]
---
### Message 2
**author_id**: Romuald GRUSON
**date**: 19/03/2025 10:45:56
**message_type**: E-mail
**subject**: Re: [T11082] - MISE A JOUR DE LA PLATEFORME
**id**: 227897
Bonjour
,
Nous relançons la mise à jour dès à présent. Votre plateforme sera de nouveau disponible en début d'après-midi.
Je reste à votre entière disposition pour toute information complémentaire.
Cordialement,
---
Support technique
---
## Informations sur l'extraction
- **Date d'extraction**: 16/04/2025 15:12:11
- **Répertoire**: output/ticket_T11082/T11082_20250416_151210

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,78 @@
TICKET: T11082 - MISE A JOUR DE LA PLATEFORME
Date d'extraction: 2025-04-16 15:12:11
Nombre de messages: 5
================================================================================
********************************************************************************
*** MESSAGE TRANSFÉRÉ ***
********************************************************************************
DATE: 2025-03-19 10:40:30
DE: GEOLABO
OBJET: MISE A JOUR DE LA PLATEFORME
Bonjour,
La plateforme est en mise ce matin depuis un moment, pourra ton accéder à cette dernière en début daprès midi ?
Merci davance
GRANGIER Aurore
Téléphone:04.92.76.65.93
Télécopie:09.67.22.65.93
Adresse Email :
contact@geolabo.fr
adresse postale:
172 Chemin des Grands Jardins
04220 SAINTE TULLE
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 10:41:36
DE: OdooBot
--------------------------------------------------------------------------------
********************************************************************************
*** MESSAGE TRANSFÉRÉ ***
********************************************************************************
DATE: 2025-03-19 10:45:56
DE: Romuald GRUSON
OBJET: Re: [T11082] - MISE A JOUR DE LA PLATEFORME
Bonjour
,
Nous relançons la mise à jour dès à présent. Votre plateforme sera de nouveau disponible en début d'après-midi.
Je reste à votre entière disposition pour toute information complémentaire.
Cordialement,
---
Support technique
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 10:46:17
DE: Romuald GRUSON
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-04-03 07:51:14
DE: Romuald GRUSON
--------------------------------------------------------------------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1,37 @@
[
{
"id": 144863,
"name": "image001.jpg",
"mimetype": "image/jpeg",
"file_size": 11293,
"create_date": "2025-03-19 10:41:36",
"create_uid": [
1,
"OdooBot"
],
"description": "image001.jpg",
"res_name": "[T11082] MISE A JOUR DE LA PLATEFORME",
"creator_name": "OdooBot",
"creator_id": 1,
"download_status": "success",
"local_path": "output/ticket_T11082/T11082_20250416_151210/attachments/image001.jpg",
"error": ""
},
{
"id": "embedded_2",
"name": "image_144863.png",
"mimetype": "image/png",
"file_size": "11293",
"create_date": null,
"creator_name": "Extraction automatique",
"download_status": "success",
"local_path": "output/ticket_T11082/T11082_20250416_151210/attachments/image_144863.png",
"error": "",
"is_embedded_image": true,
"source_url": "https://odoo.cbao.fr/web/image/144863?access_token=66352c31-f885-407e-bfdd-2f092702733d",
"source": "message_embedded",
"extraction_date": "2025-04-16T15:12:11.695080",
"source_message_id": "",
"message_author": ""
}
]

View File

@ -0,0 +1,23 @@
[
{
"id": 89668,
"partner_id": [
28961,
"Fabien LAFAY"
]
},
{
"id": 89673,
"partner_id": [
29816,
"contact@geolabo.fr"
]
},
{
"id": 89674,
"partner_id": [
32165,
"Romuald GRUSON"
]
}
]

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,20 @@
{
"date_extraction": "2025-04-16T15:12:11.731269",
"ticket_id": 11061,
"ticket_code": "T11082",
"ticket_name": "MISE A JOUR DE LA PLATEFORME",
"output_dir": "output/ticket_T11082/T11082_20250416_151210",
"files": {
"ticket_info": "ticket_info.json",
"ticket_summary": "ticket_summary.json",
"messages": "all_messages.json",
"messages_raw": "messages_raw.json",
"messages_text": "all_messages.txt",
"attachments": "attachments_info.json",
"followers": "followers.json"
},
"stats": {
"messages_count": 5,
"attachments_count": 2
}
}

View File

@ -0,0 +1,56 @@
{
"id": 11061,
"name": "MISE A JOUR DE LA PLATEFORME",
"description": "<p><br></p>",
"stage_id": [
8,
"Clôturé"
],
"project_id": [
3,
"Demandes"
],
"partner_id": [
1242,
"GEOLABO"
],
"user_id": [
32,
"Romuald GRUSON"
],
"date_start": "2025-03-19 10:41:36",
"date_end": false,
"date_deadline": "2025-04-03",
"create_date": "2025-03-19 10:41:36",
"write_date": "2025-04-03 07:51:14",
"tag_ids": [
15
],
"priority": "0",
"email_from": "Contact - GEOLABO <contact@geolabo.fr>",
"email_cc": "",
"message_ids": [
228930,
227900,
227899,
227898,
227897,
227894,
227893,
227892
],
"message_follower_ids": [
89668,
89673,
89674
],
"timesheet_ids": [],
"attachment_ids": [],
"stage_id_name": "Clôturé",
"project_id_name": "Demandes",
"partner_id_name": "GEOLABO",
"user_id_name": "Romuald GRUSON",
"tag_names": [
"BRG-LAB WEB"
]
}

View File

@ -0,0 +1,16 @@
{
"id": 11061,
"code": "T11082",
"name": "MISE A JOUR DE LA PLATEFORME",
"description": "<p><br></p>",
"stage": "Clôturé",
"project": "Demandes",
"partner": "GEOLABO",
"assigned_to": "Romuald GRUSON",
"tags": [
"BRG-LAB WEB"
],
"create_date": "2025-03-19 10:41:36",
"write_date": "2025-04-03 07:51:14",
"deadline": "2025-04-03"
}

View File

@ -0,0 +1,15 @@
{
"id": "11062",
"code": "T11083",
"name": "Site bloqué après MAJ",
"description": "Point particulier :\nLe cas est bloquant\nDescription du problème :\nBonjour, le site est bloqué sur la mise a jour depuis 8h30 ce matin \"La mise à jour n'est pas possible car d'autres utilisateurs sont en train de travailler sur le site\".\n\nCordialement.",
"project_name": "Demandes",
"stage_name": "Clôturé",
"user_id": "",
"partner_id_email_from": "ROCHES ET DERIVÉS, Nicolas GOSSELIN, n.gosselin@groupemouen.fr",
"create_date": "19/03/2025 10:45:17",
"write_date_last_modification": "19/03/2025 10:47:10",
"date_d'extraction": "16/04/2025 15:12:11",
"répertoire": "output/ticket_T11083/T11083_20250416_151210",
"messages_raw_reference": "output/ticket_T11083/T11083_20250416_151210/messages_raw.json"
}

View File

@ -0,0 +1,27 @@
# Ticket T11083: Site bloqué après MAJ
## Informations du ticket
- **id**: 11062
- **code**: T11083
- **name**: Site bloqué après MAJ
- **project_name**: Demandes
- **stage_name**: Clôturé
- **user_id**:
- **partner_id/email_from**: ROCHES ET DERIVÉS, Nicolas GOSSELIN, n.gosselin@groupemouen.fr
- **create_date**: 19/03/2025 10:45:17
- **write_date/last modification**: 19/03/2025 10:47:10
- **description**:
Point particulier :
Le cas est bloquant
Description du problème :
Bonjour, le site est bloqué sur la mise a jour depuis 8h30 ce matin "La mise à jour n'est pas possible car d'autres utilisateurs sont en train de travailler sur le site".
Cordialement.
## Informations sur l'extraction
- **Date d'extraction**: 16/04/2025 15:12:11
- **Répertoire**: output/ticket_T11083/T11083_20250416_151210

View File

@ -0,0 +1,109 @@
{
"ticket_summary": {
"id": 11062,
"code": "T11083",
"name": "Site bloqué après MAJ",
"project_id": 3,
"project_name": "Demandes",
"stage_id": 8,
"stage_name": "Clôturé",
"date_extraction": "2025-04-16T15:12:10.796869"
},
"metadata": {
"message_count": {
"total": 3,
"processed": 2,
"excluded": 1
},
"cleaning_strategy": "standard",
"cleaning_config": {
"preserve_links": true,
"preserve_images": true,
"strategy": "html2text",
"preserve_doc_links": true
}
},
"messages": [
{
"id": 227895,
"body": "",
"date": "2025-03-19 10:45:17",
"author_id": [
30810,
"Support Robot"
],
"email_from": "\"Support Robot\" <quentin.faivre30@gmail.com>",
"message_type": "notification",
"parent_id": false,
"subtype_id": [
16,
"Task Created"
],
"subject": false,
"tracking_value_ids": [
177944,
177945,
177946,
177947,
177948
],
"attachment_ids": [],
"is_system": true,
"is_stage_change": true,
"is_forwarded": false,
"is_duplicate": false,
"author_details": {
"name": "Support Robot",
"email": "quentin.faivre30@gmail.com",
"is_system": true,
"id": 30810,
"phone": false,
"function": false,
"company_id": [
1,
"CBAO S.A.R.L."
]
}
},
{
"id": 227904,
"body": "",
"date": "2025-03-19 10:47:10",
"author_id": [
32165,
"Romuald GRUSON"
],
"email_from": "\"Romuald GRUSON\" <romuald@mail.cbao.fr>",
"message_type": "notification",
"parent_id": [
227895,
"[T11083] Site bloqué après MAJ"
],
"subtype_id": [
19,
"Stage Changed"
],
"subject": false,
"tracking_value_ids": [
177963
],
"attachment_ids": [],
"is_system": true,
"is_stage_change": true,
"is_forwarded": false,
"is_duplicate": false,
"author_details": {
"name": "Romuald GRUSON",
"email": "romuald@mail.cbao.fr",
"is_system": false,
"id": 32165,
"phone": false,
"function": false,
"company_id": [
1,
"CBAO S.A.R.L."
]
}
}
]
}

View File

@ -0,0 +1,27 @@
TICKET: T11083 - Site bloqué après MAJ
Date d'extraction: 2025-04-16 15:12:10
Nombre de messages: 2
================================================================================
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 10:45:17
DE: Support Robot
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 10:47:10
DE: Romuald GRUSON
--------------------------------------------------------------------------------

View File

@ -0,0 +1,23 @@
[
{
"id": 89669,
"partner_id": [
30810,
"Support Robot"
]
},
{
"id": 89670,
"partner_id": [
28961,
"Fabien LAFAY"
]
},
{
"id": 89676,
"partner_id": [
32165,
"Romuald GRUSON"
]
}
]

View File

@ -0,0 +1,98 @@
{
"ticket_id": 11062,
"ticket_code": "T11083",
"message_metadata": {
"227895": {
"is_system": true,
"is_stage_change": true,
"is_forwarded": false,
"is_duplicate": false
},
"227903": {
"is_system": true,
"is_stage_change": false,
"is_forwarded": false,
"is_duplicate": false,
"excluded": "system_message"
},
"227904": {
"is_system": true,
"is_stage_change": true,
"is_forwarded": false,
"is_duplicate": false
}
},
"messages": [
{
"id": 227895,
"body": "",
"date": "2025-03-19 10:45:17",
"author_id": [
30810,
"Support Robot"
],
"email_from": "\"Support Robot\" <quentin.faivre30@gmail.com>",
"message_type": "notification",
"parent_id": false,
"subtype_id": [
16,
"Task Created"
],
"subject": false,
"tracking_value_ids": [
177944,
177945,
177946,
177947,
177948
],
"attachment_ids": []
},
{
"id": 227903,
"body": "<p>doublon</p>",
"date": "2025-03-19 10:47:06",
"author_id": [
32165,
"Romuald GRUSON"
],
"email_from": "\"Romuald GRUSON\" <romuald@mail.cbao.fr>",
"message_type": "comment",
"parent_id": [
227895,
"[T11083] Site bloqué après MAJ"
],
"subtype_id": [
2,
"Note"
],
"subject": false,
"tracking_value_ids": [],
"attachment_ids": []
},
{
"id": 227904,
"body": "",
"date": "2025-03-19 10:47:10",
"author_id": [
32165,
"Romuald GRUSON"
],
"email_from": "\"Romuald GRUSON\" <romuald@mail.cbao.fr>",
"message_type": "notification",
"parent_id": [
227895,
"[T11083] Site bloqué après MAJ"
],
"subtype_id": [
19,
"Stage Changed"
],
"subject": false,
"tracking_value_ids": [
177963
],
"attachment_ids": []
}
]
}

View File

@ -0,0 +1,20 @@
{
"date_extraction": "2025-04-16T15:12:10.859087",
"ticket_id": 11062,
"ticket_code": "T11083",
"ticket_name": "Site bloqué après MAJ",
"output_dir": "output/ticket_T11083/T11083_20250416_151210",
"files": {
"ticket_info": "ticket_info.json",
"ticket_summary": "ticket_summary.json",
"messages": "all_messages.json",
"messages_raw": "messages_raw.json",
"messages_text": "all_messages.txt",
"attachments": "attachments_info.json",
"followers": "followers.json"
},
"stats": {
"messages_count": 2,
"attachments_count": 0
}
}

View File

@ -0,0 +1,47 @@
{
"id": 11062,
"name": "Site bloqué après MAJ",
"description": "<h1>Point particulier :</h1><ul><li><b>Le cas est bloquant</b></li></ul><h1>Description du problème :</h1><p>Bonjour, le site est bloqué sur la mise a jour depuis 8h30 ce matin \"La mise à jour n'est pas possible car d'autres utilisateurs sont en train de travailler sur le site\".\r\n\r\nCordialement.</p>",
"stage_id": [
8,
"Clôturé"
],
"project_id": [
3,
"Demandes"
],
"partner_id": [
3886,
"ROCHES ET DERIVÉS, Nicolas GOSSELIN"
],
"user_id": false,
"date_start": "2025-03-19 10:45:17",
"date_end": false,
"date_deadline": false,
"create_date": "2025-03-19 10:45:17",
"write_date": "2025-03-19 10:47:10",
"tag_ids": [
15
],
"priority": "3",
"email_from": "n.gosselin@groupemouen.fr",
"email_cc": "",
"message_ids": [
227904,
227903,
227895
],
"message_follower_ids": [
89669,
89670,
89676
],
"timesheet_ids": [],
"attachment_ids": [],
"stage_id_name": "Clôturé",
"project_id_name": "Demandes",
"partner_id_name": "ROCHES ET DERIVÉS, Nicolas GOSSELIN",
"tag_names": [
"BRG-LAB WEB"
]
}

View File

@ -0,0 +1,16 @@
{
"id": 11062,
"code": "T11083",
"name": "Site bloqué après MAJ",
"description": "<h1>Point particulier :</h1><ul><li><b>Le cas est bloquant</b></li></ul><h1>Description du problème :</h1><p>Bonjour, le site est bloqué sur la mise a jour depuis 8h30 ce matin \"La mise à jour n'est pas possible car d'autres utilisateurs sont en train de travailler sur le site\".\r\n\r\nCordialement.</p>",
"stage": "Clôturé",
"project": "Demandes",
"partner": "ROCHES ET DERIVÉS, Nicolas GOSSELIN",
"assigned_to": "",
"tags": [
"BRG-LAB WEB"
],
"create_date": "2025-03-19 10:45:17",
"write_date": "2025-03-19 10:47:10",
"deadline": false
}

View File

@ -0,0 +1,26 @@
{
"id": "11063",
"code": "T11084",
"name": "Site bloqué après MAJ",
"description": "Point particulier :\nLe cas est bloquant\nDescription du problème :\nBonjour, le site est bloqué sur la mise a jour depuis 8h30 ce matin \"La mise à jour n'est pas possible car d'autres utilisateurs sont en train de travailler sur le site\".\n\nCordialement.",
"project_name": "Demandes",
"stage_name": "Clôturé",
"user_id": "",
"partner_id_email_from": "ROCHES ET DERIVÉS, Nicolas GOSSELIN, n.gosselin@groupemouen.fr",
"create_date": "19/03/2025 10:45:19",
"write_date_last_modification": "03/04/2025 07:51:20",
"date_deadline": "03/04/2025 00:00:00",
"messages": [
{
"author_id": "Romuald GRUSON",
"date": "19/03/2025 13:06:13",
"message_type": "E-mail",
"subject": "Re: [T11084] - Site bloqué après MAJ",
"id": "227919",
"content": "Bonjour\n,\nNous avons relancé la mise à jour sur votre plateforme BRG-LAB, celle ci est de nouveau disponible et à jour.\nJe reste à votre entière disposition pour toute information complémentaire.\nCordialement,\n---\nSupport technique\n\n---\n"
}
],
"date_d'extraction": "16/04/2025 15:12:11",
"répertoire": "output/ticket_T11084/T11084_20250416_151209",
"messages_raw_reference": "output/ticket_T11084/T11084_20250416_151209/messages_raw.json"
}

View File

@ -0,0 +1,46 @@
# Ticket T11084: Site bloqué après MAJ
## Informations du ticket
- **id**: 11063
- **code**: T11084
- **name**: Site bloqué après MAJ
- **project_name**: Demandes
- **stage_name**: Clôturé
- **user_id**:
- **partner_id/email_from**: ROCHES ET DERIVÉS, Nicolas GOSSELIN, n.gosselin@groupemouen.fr
- **create_date**: 19/03/2025 10:45:19
- **write_date/last modification**: 03/04/2025 07:51:20
- **date_deadline**: 03/04/2025 00:00:00
- **description**:
Point particulier :
Le cas est bloquant
Description du problème :
Bonjour, le site est bloqué sur la mise a jour depuis 8h30 ce matin "La mise à jour n'est pas possible car d'autres utilisateurs sont en train de travailler sur le site".
Cordialement.
## Messages
### Message 1
**author_id**: Romuald GRUSON
**date**: 19/03/2025 13:06:13
**message_type**: E-mail
**subject**: Re: [T11084] - Site bloqué après MAJ
**id**: 227919
Bonjour
,
Nous avons relancé la mise à jour sur votre plateforme BRG-LAB, celle ci est de nouveau disponible et à jour.
Je reste à votre entière disposition pour toute information complémentaire.
Cordialement,
---
Support technique
---
## Informations sur l'extraction
- **Date d'extraction**: 16/04/2025 15:12:11
- **Répertoire**: output/ticket_T11084/T11084_20250416_151209

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,56 @@
TICKET: T11084 - Site bloqué après MAJ
Date d'extraction: 2025-04-16 15:12:10
Nombre de messages: 4
================================================================================
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 10:45:20
DE: Support Robot
--------------------------------------------------------------------------------
********************************************************************************
*** MESSAGE TRANSFÉRÉ ***
********************************************************************************
DATE: 2025-03-19 13:06:13
DE: Romuald GRUSON
OBJET: Re: [T11084] - Site bloqué après MAJ
Bonjour
,
Nous avons relancé la mise à jour sur votre plateforme BRG-LAB, celle ci est de nouveau disponible et à jour.
Je reste à votre entière disposition pour toute information complémentaire.
Cordialement,
---
Support technique
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 13:06:26
DE: Romuald GRUSON
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-04-03 07:51:20
DE: Romuald GRUSON
--------------------------------------------------------------------------------

View File

@ -0,0 +1,30 @@
[
{
"id": 89671,
"partner_id": [
30810,
"Support Robot"
]
},
{
"id": 89672,
"partner_id": [
28961,
"Fabien LAFAY"
]
},
{
"id": 89682,
"partner_id": [
3886,
"ROCHES ET DERIVÉS, Nicolas GOSSELIN"
]
},
{
"id": 89683,
"partner_id": [
32165,
"Romuald GRUSON"
]
}
]

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,20 @@
{
"date_extraction": "2025-04-16T15:12:10.497997",
"ticket_id": 11063,
"ticket_code": "T11084",
"ticket_name": "Site bloqué après MAJ",
"output_dir": "output/ticket_T11084/T11084_20250416_151209",
"files": {
"ticket_info": "ticket_info.json",
"ticket_summary": "ticket_summary.json",
"messages": "all_messages.json",
"messages_raw": "messages_raw.json",
"messages_text": "all_messages.txt",
"attachments": "attachments_info.json",
"followers": "followers.json"
},
"stats": {
"messages_count": 4,
"attachments_count": 0
}
}

View File

@ -0,0 +1,55 @@
{
"id": 11063,
"name": "Site bloqué après MAJ",
"description": "<h1>Point particulier :</h1><ul><li><b>Le cas est bloquant</b></li></ul><h1>Description du problème :</h1><p>Bonjour, le site est bloqué sur la mise a jour depuis 8h30 ce matin \"La mise à jour n'est pas possible car d'autres utilisateurs sont en train de travailler sur le site\".\r\n\r\nCordialement.</p>",
"stage_id": [
8,
"Clôturé"
],
"project_id": [
3,
"Demandes"
],
"partner_id": [
3886,
"ROCHES ET DERIVÉS, Nicolas GOSSELIN"
],
"user_id": [
32,
"Romuald GRUSON"
],
"date_start": "2025-03-19 10:45:19",
"date_end": false,
"date_deadline": "2025-04-03",
"create_date": "2025-03-19 10:45:19",
"write_date": "2025-04-03 07:51:20",
"tag_ids": [
15
],
"priority": "3",
"email_from": "n.gosselin@groupemouen.fr",
"email_cc": "",
"message_ids": [
228931,
227922,
227921,
227920,
227919,
227896
],
"message_follower_ids": [
89671,
89672,
89682,
89683
],
"timesheet_ids": [],
"attachment_ids": [],
"stage_id_name": "Clôturé",
"project_id_name": "Demandes",
"partner_id_name": "ROCHES ET DERIVÉS, Nicolas GOSSELIN",
"user_id_name": "Romuald GRUSON",
"tag_names": [
"BRG-LAB WEB"
]
}

View File

@ -0,0 +1,16 @@
{
"id": 11063,
"code": "T11084",
"name": "Site bloqué après MAJ",
"description": "<h1>Point particulier :</h1><ul><li><b>Le cas est bloquant</b></li></ul><h1>Description du problème :</h1><p>Bonjour, le site est bloqué sur la mise a jour depuis 8h30 ce matin \"La mise à jour n'est pas possible car d'autres utilisateurs sont en train de travailler sur le site\".\r\n\r\nCordialement.</p>",
"stage": "Clôturé",
"project": "Demandes",
"partner": "ROCHES ET DERIVÉS, Nicolas GOSSELIN",
"assigned_to": "Romuald GRUSON",
"tags": [
"BRG-LAB WEB"
],
"create_date": "2025-03-19 10:45:19",
"write_date": "2025-04-03 07:51:20",
"deadline": "2025-04-03"
}

View File

@ -0,0 +1,26 @@
{
"id": "11064",
"code": "T11085",
"name": "cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN",
"description": "Romuald : Réponse par mail demande n° T11084",
"project_name": "Demandes",
"stage_name": "Clôturé",
"user_id": "",
"partner_id_email_from": "ROCHES ET DERIVÉS, Nicolas GOSSELIN, n.gosselin@groupemouen.fr",
"create_date": "19/03/2025 10:46:41",
"write_date_last_modification": "03/04/2025 07:51:26",
"date_deadline": "03/04/2025 00:00:00",
"messages": [
{
"author_id": "vocalia",
"date": "19/03/2025 10:44:29",
"message_type": "E-mail",
"subject": "cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN",
"id": "227902",
"content": "Veuillez trouver ci-dessous le suivi de vos appels.\nMessage : le 19/03/2025 à 11:41\nNom\nROCHES ET DERIVÉS\nPrénom\nNicolas GOSSELIN\nAdresse mail\noui\nPanne\nplus aucun droit suite a la mise a jour\nRv\nmessage répondeur\nTicket\npas concerné\nMessage\nMessage pour : LAFAY Fabien / urgence --joindre systématiquement Fabien----\nM.GOSSELIN de l entreprise roches et dérivés cherche à vous joindre, le site est bloqué depuis ce matin suite à une mise à jour. Elsa\nAdresse\n- 14790 MOUEN\nTél\n02-31-26-25-66\nE-mail\nn.gosselin@groupemouen.fr\nGsm\n06-10-56-13-06\nVos appels sur Flux RSS :\nCliquez ici\nCordialement\nAgenda5\n\n---\n"
}
],
"date_d'extraction": "16/04/2025 15:12:11",
"répertoire": "output/ticket_T11085/T11085_20250416_151209",
"messages_raw_reference": "output/ticket_T11085/T11085_20250416_151209/messages_raw.json"
}

View File

@ -0,0 +1,63 @@
# Ticket T11085: cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN
## Informations du ticket
- **id**: 11064
- **code**: T11085
- **name**: cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN
- **project_name**: Demandes
- **stage_name**: Clôturé
- **user_id**:
- **partner_id/email_from**: ROCHES ET DERIVÉS, Nicolas GOSSELIN, n.gosselin@groupemouen.fr
- **create_date**: 19/03/2025 10:46:41
- **write_date/last modification**: 03/04/2025 07:51:26
- **date_deadline**: 03/04/2025 00:00:00
- **description**:
Romuald : Réponse par mail demande n° T11084
## Messages
### Message 1
**author_id**: vocalia
**date**: 19/03/2025 10:44:29
**message_type**: E-mail
**subject**: cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN
**id**: 227902
Veuillez trouver ci-dessous le suivi de vos appels.
Message : le 19/03/2025 à 11:41
Nom
ROCHES ET DERIVÉS
Prénom
Nicolas GOSSELIN
Adresse mail
oui
Panne
plus aucun droit suite a la mise a jour
Rv
message répondeur
Ticket
pas concerné
Message
Message pour : LAFAY Fabien / urgence --joindre systématiquement Fabien----
M.GOSSELIN de l entreprise roches et dérivés cherche à vous joindre, le site est bloqué depuis ce matin suite à une mise à jour. Elsa
Adresse
- 14790 MOUEN
Tél
02-31-26-25-66
E-mail
n.gosselin@groupemouen.fr
Gsm
06-10-56-13-06
Vos appels sur Flux RSS :
Cliquez ici
Cordialement
Agenda5
---
## Informations sur l'extraction
- **Date d'extraction**: 16/04/2025 15:12:11
- **Répertoire**: output/ticket_T11085/T11085_20250416_151209

View File

@ -0,0 +1,189 @@
{
"ticket_summary": {
"id": 11064,
"code": "T11085",
"name": "cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN",
"project_id": 3,
"project_name": "Demandes",
"stage_id": 8,
"stage_name": "Clôturé",
"date_extraction": "2025-04-16T15:12:09.546064"
},
"metadata": {
"message_count": {
"total": 6,
"processed": 4,
"excluded": 2
},
"cleaning_strategy": "standard",
"cleaning_config": {
"preserve_links": true,
"preserve_images": true,
"strategy": "html2text",
"preserve_doc_links": true
}
},
"messages": [
{
"id": 227902,
"body": "Veuillez trouver ci-dessous le suivi de vos appels.\nMessage : le 19/03/2025 à 11:41\nNom\nROCHES ET DERIVÉS\nPrénom\nNicolas GOSSELIN\nAdresse mail\noui\nPanne\nplus aucun droit suite a la mise a jour\nRv\nmessage répondeur\nTicket\npas concerné\nMessage\nMessage pour : LAFAY Fabien / urgence --joindre systématiquement Fabien----\nM.GOSSELIN de l entreprise roches et dérivés cherche à vous joindre, le site est bloqué depuis ce matin suite à une mise à jour. Elsa\nAdresse\n- 14790 MOUEN\nTél\n02-31-26-25-66\nE-mail\nn.gosselin@groupemouen.fr\nGsm\n06-10-56-13-06\nVos appels sur Flux RSS :\nCliquez ici\nCordialement\nAgenda5",
"date": "2025-03-19 10:44:29",
"author_id": [
31768,
"vocalia"
],
"email_from": "vocalia@a5serv.fr",
"message_type": "email",
"parent_id": [
227901,
"[T11085] cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN"
],
"subtype_id": [
1,
"Discussions"
],
"subject": "cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN",
"tracking_value_ids": [],
"attachment_ids": [],
"is_system": false,
"is_stage_change": false,
"is_forwarded": false,
"is_duplicate": false,
"body_original": "\r\n\r\n\r\nVeuillez trouver ci-dessous le suivi de vos appels.<br><br>\r\n<img src=\"https://vocalia.a5serv.fr/mepl.png\" border=\"0\" width=\"32\" height=\"32\" style=\"vertical-align:middle\" alt=\"Message\"> <u><b>Message : le 19/03/2025 à 11:41</b></u><br><br>\r\n\r\n\r\n<table border=\"1\" cellpadding=\"3\" cellspacing=\"0\" style=\"border-width:1px; border-style:solid; border-color:#CCCCCC; border-collapse:collapse; font-size:13px; font-family:arial, helvetica, sans-serif\"><tr><td style=\"background-color:#F5F5F5\">Nom</td><td>ROCHES ET DERIVÉS</td></tr><tr><td style=\"background-color:#F5F5F5\">Prénom</td><td>Nicolas GOSSELIN</td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Adresse mail</td><td> oui</td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Panne</td><td> plus aucun droit suite a la mise a jour </td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Rv</td><td> message répondeur</td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Ticket</td><td> pas concerné</td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Message</td><td>Message pour : LAFAY Fabien / urgence --joindre systématiquement Fabien---- <br>M.GOSSELIN de l entreprise roches et dérivés cherche à vous joindre, le site est bloqué depuis ce matin suite à une mise à jour. Elsa <br><br><br><br></td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Adresse</td><td>- 14790 MOUEN</td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Tél</td><td>02-31-26-25-66</td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">E-mail</td> <td>n.gosselin@groupemouen.fr</td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Gsm</td> <td>06-10-56-13-06</td></tr></table>\r\n\r\n\r\n\r\n\r\n\r\n<br>Vos appels sur Flux RSS : <a href=\"https://vocalia.a5serv.fr/cgi-bin/synchro/irss.pl?id=22a11548aui72_jjilm7m08dhek_0110.ics\">Cliquez ici</a><br>\r\n\r\n<br>Cordialement<br><br>\r\n\r\n<br><div align=\"center\"><div style=\"text-align:center; color:#777777; font-size:0.8em\"><img src=\"https://agenda5.fr/72.png\" width=\"64\" height=\"64\" alt=\"Agenda5\" border=\"0\" title=\"Agenda5\"><br>Agenda5</div></div>\r\n<br>",
"author_details": {
"name": "vocalia",
"email": "vocalia@a5serv.fr",
"is_system": false,
"id": 31768,
"phone": false,
"function": false,
"company_id": [
1,
"CBAO S.A.R.L."
]
}
},
{
"id": 227901,
"body": "",
"date": "2025-03-19 10:46:43",
"author_id": [
2,
"OdooBot"
],
"email_from": "\"OdooBot\" <odoobot@example.com>",
"message_type": "notification",
"parent_id": false,
"subtype_id": [
16,
"Task Created"
],
"subject": false,
"tracking_value_ids": [
177958,
177959,
177960,
177961,
177962
],
"attachment_ids": [],
"is_system": true,
"is_stage_change": true,
"is_forwarded": false,
"is_duplicate": false,
"author_details": {
"name": "OdooBot",
"email": "odoobot@example.com",
"is_system": true,
"id": 2,
"phone": false,
"function": false,
"company_id": [
1,
"CBAO S.A.R.L."
]
}
},
{
"id": 227925,
"body": "",
"date": "2025-03-19 13:07:53",
"author_id": [
32165,
"Romuald GRUSON"
],
"email_from": "\"Romuald GRUSON\" <romuald@mail.cbao.fr>",
"message_type": "notification",
"parent_id": [
227901,
"[T11085] cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN"
],
"subtype_id": [
19,
"Stage Changed"
],
"subject": false,
"tracking_value_ids": [
177989,
177990
],
"attachment_ids": [],
"is_system": true,
"is_stage_change": true,
"is_forwarded": false,
"is_duplicate": false,
"author_details": {
"name": "Romuald GRUSON",
"email": "romuald@mail.cbao.fr",
"is_system": false,
"id": 32165,
"phone": false,
"function": false,
"company_id": [
1,
"CBAO S.A.R.L."
]
}
},
{
"id": 228932,
"body": "",
"date": "2025-04-03 07:51:26",
"author_id": [
32165,
"Romuald GRUSON"
],
"email_from": "\"Romuald GRUSON\" <romuald@mail.cbao.fr>",
"message_type": "notification",
"parent_id": [
227901,
"[T11085] cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN"
],
"subtype_id": [
19,
"Stage Changed"
],
"subject": false,
"tracking_value_ids": [
179060
],
"attachment_ids": [],
"is_system": true,
"is_stage_change": true,
"is_forwarded": false,
"is_duplicate": false,
"author_details": {
"name": "Romuald GRUSON",
"email": "romuald@mail.cbao.fr",
"is_system": false,
"id": 32165,
"phone": false,
"function": false,
"company_id": [
1,
"CBAO S.A.R.L."
]
}
}
]
}

View File

@ -0,0 +1,74 @@
TICKET: T11085 - cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN
Date d'extraction: 2025-04-16 15:12:09
Nombre de messages: 4
================================================================================
DATE: 2025-03-19 10:44:29
DE: vocalia
OBJET: cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN
Veuillez trouver ci-dessous le suivi de vos appels.
Message : le 19/03/2025 à 11:41
Nom
ROCHES ET DERIVÉS
Prénom
Nicolas GOSSELIN
Adresse mail
oui
Panne
plus aucun droit suite a la mise a jour
Rv
message répondeur
Ticket
pas concerné
Message
Message pour : LAFAY Fabien / urgence --joindre systématiquement Fabien----
M.GOSSELIN de l entreprise roches et dérivés cherche à vous joindre, le site est bloqué depuis ce matin suite à une mise à jour. Elsa
Adresse
- 14790 MOUEN
Tél
02-31-26-25-66
E-mail
n.gosselin@groupemouen.fr
Gsm
06-10-56-13-06
Vos appels sur Flux RSS :
Cliquez ici
Cordialement
Agenda5
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 10:46:43
DE: OdooBot
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 13:07:53
DE: Romuald GRUSON
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-04-03 07:51:26
DE: Romuald GRUSON
--------------------------------------------------------------------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

View File

@ -0,0 +1,36 @@
[
{
"id": "embedded_1",
"name": "mepl.png",
"mimetype": "image/png",
"file_size": "574",
"create_date": null,
"creator_name": "Extraction automatique",
"download_status": "success",
"local_path": "output/ticket_T11085/T11085_20250416_151209/attachments/mepl.png",
"error": "",
"is_embedded_image": true,
"source_url": "https://vocalia.a5serv.fr/mepl.png",
"source": "message_embedded",
"extraction_date": "2025-04-16T15:12:09.744949",
"source_message_id": 227902,
"message_author": "vocalia"
},
{
"id": "embedded_2",
"name": "72.png",
"mimetype": "image/png",
"file_size": "1547",
"create_date": null,
"creator_name": "Extraction automatique",
"download_status": "success",
"local_path": "output/ticket_T11085/T11085_20250416_151209/attachments/72.png",
"error": "",
"is_embedded_image": true,
"source_url": "https://agenda5.fr/72.png",
"source": "message_embedded",
"extraction_date": "2025-04-16T15:12:09.904984",
"source_message_id": 227902,
"message_author": "vocalia"
}
]

View File

@ -0,0 +1,16 @@
[
{
"id": 89675,
"partner_id": [
28961,
"Fabien LAFAY"
]
},
{
"id": 89684,
"partner_id": [
32165,
"Romuald GRUSON"
]
}
]

View File

@ -0,0 +1,184 @@
{
"ticket_id": 11064,
"ticket_code": "T11085",
"message_metadata": {
"227902": {
"is_system": false,
"is_stage_change": false,
"is_forwarded": false,
"is_duplicate": false
},
"227901": {
"is_system": true,
"is_stage_change": true,
"is_forwarded": false,
"is_duplicate": false
},
"227923": {
"is_system": true,
"is_stage_change": false,
"is_forwarded": false,
"is_duplicate": false,
"excluded": "system_message"
},
"227924": {
"is_system": true,
"is_stage_change": false,
"is_forwarded": false,
"is_duplicate": false,
"excluded": "system_message"
},
"227925": {
"is_system": true,
"is_stage_change": true,
"is_forwarded": false,
"is_duplicate": false
},
"228932": {
"is_system": true,
"is_stage_change": true,
"is_forwarded": false,
"is_duplicate": false
}
},
"messages": [
{
"id": 227902,
"body": "\r\n\r\n\r\nVeuillez trouver ci-dessous le suivi de vos appels.<br><br>\r\n<img src=\"https://vocalia.a5serv.fr/mepl.png\" border=\"0\" width=\"32\" height=\"32\" style=\"vertical-align:middle\" alt=\"Message\"> <u><b>Message : le 19/03/2025 à 11:41</b></u><br><br>\r\n\r\n\r\n<table border=\"1\" cellpadding=\"3\" cellspacing=\"0\" style=\"border-width:1px; border-style:solid; border-color:#CCCCCC; border-collapse:collapse; font-size:13px; font-family:arial, helvetica, sans-serif\"><tr><td style=\"background-color:#F5F5F5\">Nom</td><td>ROCHES ET DERIVÉS</td></tr><tr><td style=\"background-color:#F5F5F5\">Prénom</td><td>Nicolas GOSSELIN</td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Adresse mail</td><td> oui</td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Panne</td><td> plus aucun droit suite a la mise a jour </td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Rv</td><td> message répondeur</td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Ticket</td><td> pas concerné</td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Message</td><td>Message pour : LAFAY Fabien / urgence --joindre systématiquement Fabien---- <br>M.GOSSELIN de l entreprise roches et dérivés cherche à vous joindre, le site est bloqué depuis ce matin suite à une mise à jour. Elsa <br><br><br><br></td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Adresse</td><td>- 14790 MOUEN</td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Tél</td><td>02-31-26-25-66</td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">E-mail</td> <td>n.gosselin@groupemouen.fr</td></tr><tr><td style=\"vertical-align:top; background-color:#F5F5F5\">Gsm</td> <td>06-10-56-13-06</td></tr></table>\r\n\r\n\r\n\r\n\r\n\r\n<br>Vos appels sur Flux RSS : <a href=\"https://vocalia.a5serv.fr/cgi-bin/synchro/irss.pl?id=22a11548aui72_jjilm7m08dhek_0110.ics\">Cliquez ici</a><br>\r\n\r\n<br>Cordialement<br><br>\r\n\r\n<br><div align=\"center\"><div style=\"text-align:center; color:#777777; font-size:0.8em\"><img src=\"https://agenda5.fr/72.png\" width=\"64\" height=\"64\" alt=\"Agenda5\" border=\"0\" title=\"Agenda5\"><br>Agenda5</div></div>\r\n<br>",
"date": "2025-03-19 10:44:29",
"author_id": [
31768,
"vocalia"
],
"email_from": "vocalia@a5serv.fr",
"message_type": "email",
"parent_id": [
227901,
"[T11085] cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN"
],
"subtype_id": [
1,
"Discussions"
],
"subject": "cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN",
"tracking_value_ids": [],
"attachment_ids": []
},
{
"id": 227901,
"body": "",
"date": "2025-03-19 10:46:43",
"author_id": [
2,
"OdooBot"
],
"email_from": "\"OdooBot\" <odoobot@example.com>",
"message_type": "notification",
"parent_id": false,
"subtype_id": [
16,
"Task Created"
],
"subject": false,
"tracking_value_ids": [
177958,
177959,
177960,
177961,
177962
],
"attachment_ids": []
},
{
"id": 227923,
"body": "",
"date": "2025-03-19 13:07:03",
"author_id": [
32165,
"Romuald GRUSON"
],
"email_from": "\"Romuald GRUSON\" <romuald@mail.cbao.fr>",
"message_type": "notification",
"parent_id": false,
"subtype_id": [
2,
"Note"
],
"subject": false,
"tracking_value_ids": [
177987
],
"attachment_ids": []
},
{
"id": 227924,
"body": "",
"date": "2025-03-19 13:07:53",
"author_id": [
32165,
"Romuald GRUSON"
],
"email_from": "\"Romuald GRUSON\" <romuald@mail.cbao.fr>",
"message_type": "notification",
"parent_id": false,
"subtype_id": [
2,
"Note"
],
"subject": false,
"tracking_value_ids": [
177988
],
"attachment_ids": []
},
{
"id": 227925,
"body": "",
"date": "2025-03-19 13:07:53",
"author_id": [
32165,
"Romuald GRUSON"
],
"email_from": "\"Romuald GRUSON\" <romuald@mail.cbao.fr>",
"message_type": "notification",
"parent_id": [
227901,
"[T11085] cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN"
],
"subtype_id": [
19,
"Stage Changed"
],
"subject": false,
"tracking_value_ids": [
177989,
177990
],
"attachment_ids": []
},
{
"id": 228932,
"body": "",
"date": "2025-04-03 07:51:26",
"author_id": [
32165,
"Romuald GRUSON"
],
"email_from": "\"Romuald GRUSON\" <romuald@mail.cbao.fr>",
"message_type": "notification",
"parent_id": [
227901,
"[T11085] cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN"
],
"subtype_id": [
19,
"Stage Changed"
],
"subject": false,
"tracking_value_ids": [
179060
],
"attachment_ids": []
}
]
}

View File

@ -0,0 +1,20 @@
{
"date_extraction": "2025-04-16T15:12:09.938031",
"ticket_id": 11064,
"ticket_code": "T11085",
"ticket_name": "cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN",
"output_dir": "output/ticket_T11085/T11085_20250416_151209",
"files": {
"ticket_info": "ticket_info.json",
"ticket_summary": "ticket_summary.json",
"messages": "all_messages.json",
"messages_raw": "messages_raw.json",
"messages_text": "all_messages.txt",
"attachments": "attachments_info.json",
"followers": "followers.json"
},
"stats": {
"messages_count": 4,
"attachments_count": 2
}
}

View File

@ -0,0 +1,53 @@
{
"id": 11064,
"name": "cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN",
"description": "<p>Romuald : Réponse par mail demande n° T11084</p>",
"stage_id": [
8,
"Clôturé"
],
"project_id": [
3,
"Demandes"
],
"partner_id": [
3886,
"ROCHES ET DERIVÉS, Nicolas GOSSELIN"
],
"user_id": [
32,
"Romuald GRUSON"
],
"date_start": "2025-03-19 10:46:43",
"date_end": false,
"date_deadline": "2025-04-03",
"create_date": "2025-03-19 10:46:41",
"write_date": "2025-04-03 07:51:26",
"tag_ids": [
15
],
"priority": "0",
"email_from": "n.gosselin@groupemouen.fr",
"email_cc": "",
"message_ids": [
228932,
227925,
227924,
227923,
227902,
227901
],
"message_follower_ids": [
89675,
89684
],
"timesheet_ids": [],
"attachment_ids": [],
"stage_id_name": "Clôturé",
"project_id_name": "Demandes",
"partner_id_name": "ROCHES ET DERIVÉS, Nicolas GOSSELIN",
"user_id_name": "Romuald GRUSON",
"tag_names": [
"BRG-LAB WEB"
]
}

View File

@ -0,0 +1,16 @@
{
"id": 11064,
"code": "T11085",
"name": "cbao_support_technique - Message : ROCHES ET DERIV<49>S Nicolas GOSSELIN",
"description": "<p>Romuald : Réponse par mail demande n° T11084</p>",
"stage": "Clôturé",
"project": "Demandes",
"partner": "ROCHES ET DERIVÉS, Nicolas GOSSELIN",
"assigned_to": "Romuald GRUSON",
"tags": [
"BRG-LAB WEB"
],
"create_date": "2025-03-19 10:46:41",
"write_date": "2025-04-03 07:51:26",
"deadline": "2025-04-03"
}

View File

@ -0,0 +1,34 @@
{
"id": "11065",
"code": "T11086",
"name": "Erreur fatale essai VBS",
"description": "*Contenu non extractible*",
"project_name": "Demandes",
"stage_name": "Clôturé",
"user_id": "",
"partner_id_email_from": "AXYLIS (GROUPE MINIER), Delphine PILON, Delphine PILON <dpilon@axylis.com>",
"create_date": "19/03/2025 11:06:53",
"write_date_last_modification": "03/04/2025 07:51:32",
"date_deadline": "03/04/2025 00:00:00",
"messages": [
{
"author_id": "Delphine PILON",
"date": "19/03/2025 11:02:12",
"message_type": "E-mail",
"subject": "Erreur fatale essai VBS",
"id": "227908",
"content": "Bonjour,\nSur tous les essais VBS, jai le message derreur ci-dessous qui saffiche.\nPouvez-vous, sil vous plait, résoudre le problème assez rapidement ?\nMes clients attendent leurs résultats\n\n- image002.png (image/png) [ID: 144867]\n- image001.png (image/png) [ID: 144865]\n\n---\n\n"
},
{
"author_id": "Romuald GRUSON",
"date": "19/03/2025 13:03:13",
"message_type": "E-mail",
"subject": "Re: [T11086] - Erreur fatale essai VBS",
"id": "227915",
"content": "Bonjour\n,\nNous avons déployé en urgence un patch ce midi pour corriger cette anomalie. Nous sommes désolés pour ce désagrément, une erreur de compilation des données s'est glissée dans le déploiement de notre mise à jour de cette nuit.\nJe reste à votre entière disposition pour toute information complémentaire.\nCordialement,\n---\nSupport technique\n\n---\n"
}
],
"date_d'extraction": "16/04/2025 15:12:11",
"répertoire": "output/ticket_T11086/T11086_20250416_151208",
"messages_raw_reference": "output/ticket_T11086/T11086_20250416_151208/messages_raw.json"
}

View File

@ -0,0 +1,58 @@
# Ticket T11086: Erreur fatale essai VBS
## Informations du ticket
- **id**: 11065
- **code**: T11086
- **name**: Erreur fatale essai VBS
- **project_name**: Demandes
- **stage_name**: Clôturé
- **user_id**:
- **partner_id/email_from**: AXYLIS (GROUPE MINIER), Delphine PILON, Delphine PILON <dpilon@axylis.com>
- **create_date**: 19/03/2025 11:06:53
- **write_date/last modification**: 03/04/2025 07:51:32
- **date_deadline**: 03/04/2025 00:00:00
- **description**:
*Contenu non extractible*
## Messages
### Message 1
**author_id**: Delphine PILON
**date**: 19/03/2025 11:02:12
**message_type**: E-mail
**subject**: Erreur fatale essai VBS
**id**: 227908
Bonjour,
Sur tous les essais VBS, jai le message derreur ci-dessous qui saffiche.
Pouvez-vous, sil vous plait, résoudre le problème assez rapidement ?
Mes clients attendent leurs résultats
**attachment_ids**:
- image002.png (image/png) [ID: 144867]
- image001.png (image/png) [ID: 144865]
---
### Message 2
**author_id**: Romuald GRUSON
**date**: 19/03/2025 13:03:13
**message_type**: E-mail
**subject**: Re: [T11086] - Erreur fatale essai VBS
**id**: 227915
Bonjour
,
Nous avons déployé en urgence un patch ce midi pour corriger cette anomalie. Nous sommes désolés pour ce désagrément, une erreur de compilation des données s'est glissée dans le déploiement de notre mise à jour de cette nuit.
Je reste à votre entière disposition pour toute information complémentaire.
Cordialement,
---
Support technique
---
## Informations sur l'extraction
- **Date d'extraction**: 16/04/2025 15:12:11
- **Répertoire**: output/ticket_T11086/T11086_20250416_151208

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,67 @@
TICKET: T11086 - Erreur fatale essai VBS
Date d'extraction: 2025-04-16 15:12:08
Nombre de messages: 5
================================================================================
DATE: 2025-03-19 11:02:12
DE: Delphine PILON
OBJET: Erreur fatale essai VBS
Bonjour,
Sur tous les essais VBS, jai le message derreur ci-dessous qui saffiche.
Pouvez-vous, sil vous plait, résoudre le problème assez rapidement ?
Mes clients attendent leurs résultats
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 11:06:56
DE: OdooBot
--------------------------------------------------------------------------------
********************************************************************************
*** MESSAGE TRANSFÉRÉ ***
********************************************************************************
DATE: 2025-03-19 13:03:13
DE: Romuald GRUSON
OBJET: Re: [T11086] - Erreur fatale essai VBS
Bonjour
,
Nous avons déployé en urgence un patch ce midi pour corriger cette anomalie. Nous sommes désolés pour ce désagrément, une erreur de compilation des données s'est glissée dans le déploiement de notre mise à jour de cette nuit.
Je reste à votre entière disposition pour toute information complémentaire.
Cordialement,
---
Support technique
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 13:04:19
DE: Romuald GRUSON
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-04-03 07:51:32
DE: Romuald GRUSON
--------------------------------------------------------------------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

View File

@ -0,0 +1,72 @@
[
{
"id": 144867,
"name": "image002.png",
"mimetype": "image/png",
"file_size": 286527,
"create_date": "2025-03-19 11:06:53",
"create_uid": [
1,
"OdooBot"
],
"description": "image002.png",
"res_name": "[T11086] Erreur fatale essai VBS",
"creator_name": "OdooBot",
"creator_id": 1,
"download_status": "success",
"local_path": "output/ticket_T11086/T11086_20250416_151208/attachments/image002.png",
"error": ""
},
{
"id": 144865,
"name": "image001.png",
"mimetype": "image/png",
"file_size": 129352,
"create_date": "2025-03-19 11:06:53",
"create_uid": [
1,
"OdooBot"
],
"description": "image001.png",
"res_name": "[T11086] Erreur fatale essai VBS",
"creator_name": "OdooBot",
"creator_id": 1,
"download_status": "success",
"local_path": "output/ticket_T11086/T11086_20250416_151208/attachments/image001.png",
"error": ""
},
{
"id": "embedded_3",
"name": "image_144867.png",
"mimetype": "image/png",
"file_size": "286527",
"create_date": null,
"creator_name": "Extraction automatique",
"download_status": "success",
"local_path": "output/ticket_T11086/T11086_20250416_151208/attachments/image_144867.png",
"error": "",
"is_embedded_image": true,
"source_url": "https://odoo.cbao.fr/web/image/144867?access_token=79dd4392-8593-432c-b8ba-6bb833d67851",
"source": "message_embedded",
"extraction_date": "2025-04-16T15:12:08.858190",
"source_message_id": "",
"message_author": ""
},
{
"id": "embedded_4",
"name": "image_144865.png",
"mimetype": "image/png",
"file_size": "129352",
"create_date": null,
"creator_name": "Extraction automatique",
"download_status": "success",
"local_path": "output/ticket_T11086/T11086_20250416_151208/attachments/image_144865.png",
"error": "",
"is_embedded_image": true,
"source_url": "https://odoo.cbao.fr/web/image/144865?access_token=833e3881-9c0d-41a6-8f95-0ff4edfbabe8",
"source": "message_embedded",
"extraction_date": "2025-04-16T15:12:09.018414",
"source_message_id": "",
"message_author": ""
}
]

View File

@ -0,0 +1,23 @@
[
{
"id": 89678,
"partner_id": [
28961,
"Fabien LAFAY"
]
},
{
"id": 89680,
"partner_id": [
26137,
"AXYLIS (GROUPE MINIER), Delphine PILON"
]
},
{
"id": 89681,
"partner_id": [
32165,
"Romuald GRUSON"
]
}
]

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,20 @@
{
"date_extraction": "2025-04-16T15:12:09.052708",
"ticket_id": 11065,
"ticket_code": "T11086",
"ticket_name": "Erreur fatale essai VBS",
"output_dir": "output/ticket_T11086/T11086_20250416_151208",
"files": {
"ticket_info": "ticket_info.json",
"ticket_summary": "ticket_summary.json",
"messages": "all_messages.json",
"messages_raw": "messages_raw.json",
"messages_text": "all_messages.txt",
"attachments": "attachments_info.json",
"followers": "followers.json"
},
"stats": {
"messages_count": 5,
"attachments_count": 4
}
}

View File

@ -0,0 +1,56 @@
{
"id": 11065,
"name": "Erreur fatale essai VBS",
"description": "<p><br></p>",
"stage_id": [
8,
"Clôturé"
],
"project_id": [
3,
"Demandes"
],
"partner_id": [
26137,
"AXYLIS (GROUPE MINIER), Delphine PILON"
],
"user_id": [
32,
"Romuald GRUSON"
],
"date_start": "2025-03-19 11:06:56",
"date_end": false,
"date_deadline": "2025-04-03",
"create_date": "2025-03-19 11:06:53",
"write_date": "2025-04-03 07:51:32",
"tag_ids": [
15
],
"priority": "0",
"email_from": "Delphine PILON <dpilon@axylis.com>",
"email_cc": "",
"message_ids": [
228933,
227918,
227917,
227916,
227915,
227909,
227908,
227907
],
"message_follower_ids": [
89678,
89680,
89681
],
"timesheet_ids": [],
"attachment_ids": [],
"stage_id_name": "Clôturé",
"project_id_name": "Demandes",
"partner_id_name": "AXYLIS (GROUPE MINIER), Delphine PILON",
"user_id_name": "Romuald GRUSON",
"tag_names": [
"BRG-LAB WEB"
]
}

View File

@ -0,0 +1,16 @@
{
"id": 11065,
"code": "T11086",
"name": "Erreur fatale essai VBS",
"description": "<p><br></p>",
"stage": "Clôturé",
"project": "Demandes",
"partner": "AXYLIS (GROUPE MINIER), Delphine PILON",
"assigned_to": "Romuald GRUSON",
"tags": [
"BRG-LAB WEB"
],
"create_date": "2025-03-19 11:06:53",
"write_date": "2025-04-03 07:51:32",
"deadline": "2025-04-03"
}

View File

@ -0,0 +1,34 @@
{
"id": "11066",
"code": "T11087",
"name": "erreur fatale essai aplatissement",
"description": "*Contenu non extractible*",
"project_name": "Demandes",
"stage_name": "Clôturé",
"user_id": "",
"partner_id_email_from": "AXYLIS (GROUPE MINIER), Delphine PILON, Delphine PILON <dpilon@axylis.com>",
"create_date": "19/03/2025 11:37:08",
"write_date_last_modification": "03/04/2025 07:51:38",
"date_deadline": "03/04/2025 00:00:00",
"messages": [
{
"author_id": "Delphine PILON",
"date": "19/03/2025 11:33:40",
"message_type": "E-mail",
"subject": "erreur fatale essai aplatissement",
"id": "227911",
"content": "Rebonjour,\nJai également une erreur fatale sur lessai aplatissement.\nPouvez-vous, sil vous plait, debugger lensemble des essais bloqués\nMerci\nBien cordialement\n\n- image001.png (image/png) [ID: 144870]\n\n---\n\n"
},
{
"author_id": "Romuald GRUSON",
"date": "19/03/2025 13:10:56",
"message_type": "E-mail",
"subject": "Re: [T11087] - erreur fatale essai aplatissement",
"id": "227926",
"content": "Bonjour\n,\nNous avons déployé un patch ce midi pour corriger cette anomalie. Nous sommes désolés pour ce désagrément, une erreur de compilation des données s'est glissée dans le déploiement de notre mise à jour de cette nuit.\nJe reste à votre entière disposition pour toute information complémentaire.\nCordialement,\n---\nSupport technique\n\n---\n"
}
],
"date_d'extraction": "16/04/2025 15:12:11",
"répertoire": "output/ticket_T11087/T11087_20250416_151207",
"messages_raw_reference": "output/ticket_T11087/T11087_20250416_151207/messages_raw.json"
}

View File

@ -0,0 +1,58 @@
# Ticket T11087: erreur fatale essai aplatissement
## Informations du ticket
- **id**: 11066
- **code**: T11087
- **name**: erreur fatale essai aplatissement
- **project_name**: Demandes
- **stage_name**: Clôturé
- **user_id**:
- **partner_id/email_from**: AXYLIS (GROUPE MINIER), Delphine PILON, Delphine PILON <dpilon@axylis.com>
- **create_date**: 19/03/2025 11:37:08
- **write_date/last modification**: 03/04/2025 07:51:38
- **date_deadline**: 03/04/2025 00:00:00
- **description**:
*Contenu non extractible*
## Messages
### Message 1
**author_id**: Delphine PILON
**date**: 19/03/2025 11:33:40
**message_type**: E-mail
**subject**: erreur fatale essai aplatissement
**id**: 227911
Rebonjour,
Jai également une erreur fatale sur lessai aplatissement.
Pouvez-vous, sil vous plait, debugger lensemble des essais bloqués
Merci
Bien cordialement
**attachment_ids**:
- image001.png (image/png) [ID: 144870]
---
### Message 2
**author_id**: Romuald GRUSON
**date**: 19/03/2025 13:10:56
**message_type**: E-mail
**subject**: Re: [T11087] - erreur fatale essai aplatissement
**id**: 227926
Bonjour
,
Nous avons déployé un patch ce midi pour corriger cette anomalie. Nous sommes désolés pour ce désagrément, une erreur de compilation des données s'est glissée dans le déploiement de notre mise à jour de cette nuit.
Je reste à votre entière disposition pour toute information complémentaire.
Cordialement,
---
Support technique
---
## Informations sur l'extraction
- **Date d'extraction**: 16/04/2025 15:12:11
- **Répertoire**: output/ticket_T11087/T11087_20250416_151207

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,68 @@
TICKET: T11087 - erreur fatale essai aplatissement
Date d'extraction: 2025-04-16 15:12:07
Nombre de messages: 5
================================================================================
DATE: 2025-03-19 11:33:40
DE: Delphine PILON
OBJET: erreur fatale essai aplatissement
Rebonjour,
Jai également une erreur fatale sur lessai aplatissement.
Pouvez-vous, sil vous plait, debugger lensemble des essais bloqués
Merci
Bien cordialement
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 11:37:10
DE: OdooBot
--------------------------------------------------------------------------------
********************************************************************************
*** MESSAGE TRANSFÉRÉ ***
********************************************************************************
DATE: 2025-03-19 13:10:56
DE: Romuald GRUSON
OBJET: Re: [T11087] - erreur fatale essai aplatissement
Bonjour
,
Nous avons déployé un patch ce midi pour corriger cette anomalie. Nous sommes désolés pour ce désagrément, une erreur de compilation des données s'est glissée dans le déploiement de notre mise à jour de cette nuit.
Je reste à votre entière disposition pour toute information complémentaire.
Cordialement,
---
Support technique
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 13:11:24
DE: Romuald GRUSON
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-04-03 07:51:38
DE: Romuald GRUSON
--------------------------------------------------------------------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

View File

@ -0,0 +1,37 @@
[
{
"id": 144870,
"name": "image001.png",
"mimetype": "image/png",
"file_size": 286527,
"create_date": "2025-03-19 11:37:08",
"create_uid": [
1,
"OdooBot"
],
"description": "image001.png",
"res_name": "[T11087] erreur fatale essai aplatissement",
"creator_name": "OdooBot",
"creator_id": 1,
"download_status": "success",
"local_path": "output/ticket_T11087/T11087_20250416_151207/attachments/image001.png",
"error": ""
},
{
"id": "embedded_2",
"name": "image_144870.png",
"mimetype": "image/png",
"file_size": "286527",
"create_date": null,
"creator_name": "Extraction automatique",
"download_status": "success",
"local_path": "output/ticket_T11087/T11087_20250416_151207/attachments/image_144870.png",
"error": "",
"is_embedded_image": true,
"source_url": "https://odoo.cbao.fr/web/image/144870?access_token=e93edd3a-9ebe-41ce-b525-c734d0e7864d",
"source": "message_embedded",
"extraction_date": "2025-04-16T15:12:07.968565",
"source_message_id": "",
"message_author": ""
}
]

View File

@ -0,0 +1,23 @@
[
{
"id": 89679,
"partner_id": [
28961,
"Fabien LAFAY"
]
},
{
"id": 89685,
"partner_id": [
26137,
"AXYLIS (GROUPE MINIER), Delphine PILON"
]
},
{
"id": 89686,
"partner_id": [
32165,
"Romuald GRUSON"
]
}
]

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,20 @@
{
"date_extraction": "2025-04-16T15:12:08.003333",
"ticket_id": 11066,
"ticket_code": "T11087",
"ticket_name": "erreur fatale essai aplatissement",
"output_dir": "output/ticket_T11087/T11087_20250416_151207",
"files": {
"ticket_info": "ticket_info.json",
"ticket_summary": "ticket_summary.json",
"messages": "all_messages.json",
"messages_raw": "messages_raw.json",
"messages_text": "all_messages.txt",
"attachments": "attachments_info.json",
"followers": "followers.json"
},
"stats": {
"messages_count": 5,
"attachments_count": 2
}
}

View File

@ -0,0 +1,56 @@
{
"id": 11066,
"name": "erreur fatale essai aplatissement",
"description": "<p><br></p>",
"stage_id": [
8,
"Clôturé"
],
"project_id": [
3,
"Demandes"
],
"partner_id": [
26137,
"AXYLIS (GROUPE MINIER), Delphine PILON"
],
"user_id": [
32,
"Romuald GRUSON"
],
"date_start": "2025-03-19 11:37:09",
"date_end": false,
"date_deadline": "2025-04-03",
"create_date": "2025-03-19 11:37:08",
"write_date": "2025-04-03 07:51:38",
"tag_ids": [
15
],
"priority": "0",
"email_from": "Delphine PILON <dpilon@axylis.com>",
"email_cc": "",
"message_ids": [
228934,
227929,
227928,
227927,
227926,
227912,
227911,
227910
],
"message_follower_ids": [
89679,
89685,
89686
],
"timesheet_ids": [],
"attachment_ids": [],
"stage_id_name": "Clôturé",
"project_id_name": "Demandes",
"partner_id_name": "AXYLIS (GROUPE MINIER), Delphine PILON",
"user_id_name": "Romuald GRUSON",
"tag_names": [
"BRG-LAB WEB"
]
}

View File

@ -0,0 +1,16 @@
{
"id": 11066,
"code": "T11087",
"name": "erreur fatale essai aplatissement",
"description": "<p><br></p>",
"stage": "Clôturé",
"project": "Demandes",
"partner": "AXYLIS (GROUPE MINIER), Delphine PILON",
"assigned_to": "Romuald GRUSON",
"tags": [
"BRG-LAB WEB"
],
"create_date": "2025-03-19 11:37:08",
"write_date": "2025-04-03 07:51:38",
"deadline": "2025-04-03"
}

View File

@ -0,0 +1,34 @@
{
"id": "11067",
"code": "T11088",
"name": "BUG mise à jour",
"description": "*Contenu non extractible*",
"project_name": "Demandes",
"stage_name": "Clôturé",
"user_id": "",
"partner_id_email_from": "CONSEIL DEPARTEMENTAL DU MORBIHAN (56), Dominique CARVAL, CARVAL Dominique <dominique.carval@morbihan.fr>",
"create_date": "19/03/2025 13:21:47",
"write_date_last_modification": "03/04/2025 07:51:44",
"date_deadline": "03/04/2025 00:00:00",
"messages": [
{
"author_id": "Dominique CARVAL",
"date": "19/03/2025 13:20:33",
"message_type": "E-mail",
"subject": "BUG mise à jour",
"id": "227965",
"content": "*Message transféré - contenu non extractible*\n\n- image002.png (image/png) [ID: 144875]\n- image001.png (image/png) [ID: 144873]\n\n---\n\n"
},
{
"author_id": "Romuald GRUSON",
"date": "19/03/2025 13:49:59",
"message_type": "E-mail",
"subject": "Re: [T11088] - BUG mise à jour",
"id": "227984",
"content": "Bonjour\n,\nNous avons relancé la mise à jour sur votre plateforme BRG-LAB, celle ci sera disponible dans quelques instants.\nJe reste à votre entière disposition pour toute information complémentaire.\nCordialement,\n---\nSupport technique\n\n---\n"
}
],
"date_d'extraction": "16/04/2025 15:12:11",
"répertoire": "output/ticket_T11088/T11088_20250416_151205",
"messages_raw_reference": "output/ticket_T11088/T11088_20250416_151205/messages_raw.json"
}

View File

@ -0,0 +1,55 @@
# Ticket T11088: BUG mise à jour
## Informations du ticket
- **id**: 11067
- **code**: T11088
- **name**: BUG mise à jour
- **project_name**: Demandes
- **stage_name**: Clôturé
- **user_id**:
- **partner_id/email_from**: CONSEIL DEPARTEMENTAL DU MORBIHAN (56), Dominique CARVAL, CARVAL Dominique <dominique.carval@morbihan.fr>
- **create_date**: 19/03/2025 13:21:47
- **write_date/last modification**: 03/04/2025 07:51:44
- **date_deadline**: 03/04/2025 00:00:00
- **description**:
*Contenu non extractible*
## Messages
### Message 1
**author_id**: Dominique CARVAL
**date**: 19/03/2025 13:20:33
**message_type**: E-mail
**subject**: BUG mise à jour
**id**: 227965
*Message transféré - contenu non extractible*
**attachment_ids**:
- image002.png (image/png) [ID: 144875]
- image001.png (image/png) [ID: 144873]
---
### Message 2
**author_id**: Romuald GRUSON
**date**: 19/03/2025 13:49:59
**message_type**: E-mail
**subject**: Re: [T11088] - BUG mise à jour
**id**: 227984
Bonjour
,
Nous avons relancé la mise à jour sur votre plateforme BRG-LAB, celle ci sera disponible dans quelques instants.
Je reste à votre entière disposition pour toute information complémentaire.
Cordialement,
---
Support technique
---
## Informations sur l'extraction
- **Date d'extraction**: 16/04/2025 15:12:11
- **Répertoire**: output/ticket_T11088/T11088_20250416_151205

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,68 @@
TICKET: T11088 - BUG mise à jour
Date d'extraction: 2025-04-16 15:12:06
Nombre de messages: 5
================================================================================
********************************************************************************
*** MESSAGE TRANSFÉRÉ ***
********************************************************************************
DATE: 2025-03-19 13:20:33
DE: Dominique CARVAL
OBJET: BUG mise à jour
*Message transféré - contenu non extractible*
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 13:21:49
DE: OdooBot
--------------------------------------------------------------------------------
********************************************************************************
*** MESSAGE TRANSFÉRÉ ***
********************************************************************************
DATE: 2025-03-19 13:49:59
DE: Romuald GRUSON
OBJET: Re: [T11088] - BUG mise à jour
Bonjour
,
Nous avons relancé la mise à jour sur votre plateforme BRG-LAB, celle ci sera disponible dans quelques instants.
Je reste à votre entière disposition pour toute information complémentaire.
Cordialement,
---
Support technique
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 13:50:01
DE: Romuald GRUSON
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-04-03 07:51:44
DE: Romuald GRUSON
--------------------------------------------------------------------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1,72 @@
[
{
"id": 144875,
"name": "image002.png",
"mimetype": "image/png",
"file_size": 5417,
"create_date": "2025-03-19 13:21:47",
"create_uid": [
1,
"OdooBot"
],
"description": "image002.png",
"res_name": "[T11088] BUG mise à jour",
"creator_name": "OdooBot",
"creator_id": 1,
"download_status": "success",
"local_path": "output/ticket_T11088/T11088_20250416_151205/attachments/image002.png",
"error": ""
},
{
"id": 144873,
"name": "image001.png",
"mimetype": "image/png",
"file_size": 932420,
"create_date": "2025-03-19 13:21:47",
"create_uid": [
1,
"OdooBot"
],
"description": "image001.png",
"res_name": "[T11088] BUG mise à jour",
"creator_name": "OdooBot",
"creator_id": 1,
"download_status": "success",
"local_path": "output/ticket_T11088/T11088_20250416_151205/attachments/image001.png",
"error": ""
},
{
"id": "embedded_3",
"name": "image_144875.png",
"mimetype": "image/png",
"file_size": "5417",
"create_date": null,
"creator_name": "Extraction automatique",
"download_status": "success",
"local_path": "output/ticket_T11088/T11088_20250416_151205/attachments/image_144875.png",
"error": "",
"is_embedded_image": true,
"source_url": "https://odoo.cbao.fr/web/image/144875?access_token=5c43b30e-d037-4c34-8389-12293cf95f29",
"source": "message_embedded",
"extraction_date": "2025-04-16T15:12:06.841605",
"source_message_id": "",
"message_author": ""
},
{
"id": "embedded_4",
"name": "image_144873.png",
"mimetype": "image/png",
"file_size": "932420",
"create_date": null,
"creator_name": "Extraction automatique",
"download_status": "success",
"local_path": "output/ticket_T11088/T11088_20250416_151205/attachments/image_144873.png",
"error": "",
"is_embedded_image": true,
"source_url": "https://odoo.cbao.fr/web/image/144873?access_token=fb4b0cad-765e-4755-af83-b096dd46d172",
"source": "message_embedded",
"extraction_date": "2025-04-16T15:12:07.078268",
"source_message_id": "",
"message_author": ""
}
]

View File

@ -0,0 +1,23 @@
[
{
"id": 89691,
"partner_id": [
28961,
"Fabien LAFAY"
]
},
{
"id": 89693,
"partner_id": [
5144,
"CONSEIL DEPARTEMENTAL DU MORBIHAN (56), Dominique CARVAL"
]
},
{
"id": 89694,
"partner_id": [
32165,
"Romuald GRUSON"
]
}
]

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,20 @@
{
"date_extraction": "2025-04-16T15:12:07.110465",
"ticket_id": 11067,
"ticket_code": "T11088",
"ticket_name": "BUG mise à jour",
"output_dir": "output/ticket_T11088/T11088_20250416_151205",
"files": {
"ticket_info": "ticket_info.json",
"ticket_summary": "ticket_summary.json",
"messages": "all_messages.json",
"messages_raw": "messages_raw.json",
"messages_text": "all_messages.txt",
"attachments": "attachments_info.json",
"followers": "followers.json"
},
"stats": {
"messages_count": 5,
"attachments_count": 4
}
}

View File

@ -0,0 +1,56 @@
{
"id": 11067,
"name": "BUG mise à jour",
"description": "<p><br></p>",
"stage_id": [
8,
"Clôturé"
],
"project_id": [
3,
"Demandes"
],
"partner_id": [
5144,
"CONSEIL DEPARTEMENTAL DU MORBIHAN (56), Dominique CARVAL"
],
"user_id": [
32,
"Romuald GRUSON"
],
"date_start": "2025-03-19 13:21:49",
"date_end": false,
"date_deadline": "2025-04-03",
"create_date": "2025-03-19 13:21:47",
"write_date": "2025-04-03 07:51:44",
"tag_ids": [
15
],
"priority": "0",
"email_from": "CARVAL Dominique <dominique.carval@morbihan.fr>",
"email_cc": "",
"message_ids": [
228935,
227996,
227986,
227985,
227984,
227966,
227965,
227964
],
"message_follower_ids": [
89691,
89693,
89694
],
"timesheet_ids": [],
"attachment_ids": [],
"stage_id_name": "Clôturé",
"project_id_name": "Demandes",
"partner_id_name": "CONSEIL DEPARTEMENTAL DU MORBIHAN (56), Dominique CARVAL",
"user_id_name": "Romuald GRUSON",
"tag_names": [
"BRG-LAB WEB"
]
}

View File

@ -0,0 +1,16 @@
{
"id": 11067,
"code": "T11088",
"name": "BUG mise à jour",
"description": "<p><br></p>",
"stage": "Clôturé",
"project": "Demandes",
"partner": "CONSEIL DEPARTEMENTAL DU MORBIHAN (56), Dominique CARVAL",
"assigned_to": "Romuald GRUSON",
"tags": [
"BRG-LAB WEB"
],
"create_date": "2025-03-19 13:21:47",
"write_date": "2025-04-03 07:51:44",
"deadline": "2025-04-03"
}

View File

@ -0,0 +1,57 @@
{
"id": "11068",
"code": "T11089",
"name": "Problème création feuille paillasse béton",
"description": "*Contenu non extractible*",
"project_name": "Demandes",
"stage_name": "Clôturé",
"user_id": "",
"partner_id_email_from": "CONSEIL DEPARTEMENTAL DE LA SARTHE (72), Contact Laboratoire routier, Contact Laboratoire Routier <laboratoire.routier@sarthe.fr>",
"create_date": "19/03/2025 15:06:44",
"write_date_last_modification": "04/04/2025 08:06:34",
"date_deadline": "04/04/2025 00:00:00",
"messages": [
{
"author_id": "Contact Laboratoire routier",
"date": "19/03/2025 15:02:29",
"message_type": "E-mail",
"subject": "Problème création feuille paillasse béton",
"id": "228002",
"content": "Bonjour,\nJe rencontre un problème pour créer des échantillons d'éprouvettes béton, ci-joint capture d'écran.\nJ'en ai déjà créé 3 depuis ce matin, sans souci et là, une fois de plus, un beug alors que par défaut c'est BRG LAB qui nous impose ses numéros en suite logique.\nje suis donc bloquée et je ne peux plus travailler.\nMerci de faire le nécessaire rapidement.\ncordialement\nPeggy BRIERE\nLaborantin routier\nDépartement de la Sarthe\n\n- création eprouvette béton.PNG (image/png) [ID: 144880]\n\n---\n\n"
},
{
"author_id": "Romuald GRUSON",
"date": "19/03/2025 15:36:17",
"message_type": "E-mail",
"subject": "Re: [T11089] - Problème création feuille paillasse béton",
"id": "228005",
"content": "Bonjour\n,\nNous constatons bien le dysfonctionnement d'incrémentation sur votre prochain échantillon de béton. Pour y remédier, vous pouvez renseigner manuellement le prélèvement indiqué +1. Après cette action, le dysfonctionnement sera résolu et la numérotation sincrémente correctement.\nJe reste à votre entière disposition pour toute information complémentaire.\nCordialement,\n---\nSupport technique\n\n---\n\n"
},
{
"author_id": "Contact Laboratoire routier",
"date": "20/03/2025 06:55:41",
"message_type": "E-mail",
"subject": "RE: [T11089] - Problème création feuille paillasse béton",
"id": "228011",
"content": "Bonjour,\nCela ne fonctionne toujours pas même après votre manip.\nMerci de faire le nécessaire car nous sommes toujours bloqué !!!!!\ncordialement\nPeggy BRIERE\nLaborantin routier\nDépartement de la Sarthe\n\n---\n\n"
},
{
"author_id": "Romuald GRUSON",
"date": "20/03/2025 08:10:58",
"message_type": "Système",
"id": "228032",
"content": "20/03/2025 09:10 Plusieurs appels non répondu\n\n---\n\n"
},
{
"author_id": "Romuald GRUSON",
"date": "20/03/2025 08:17:59",
"message_type": "E-mail",
"subject": "Re: [T11089] - Problème création feuille paillasse béton",
"id": "228033",
"content": "Bonjour\n,\nLe dysfonctionnement survient lorsqu'un échantillon a été réalisé sur l'année précédente au prélèvement.\nLa solution la plus simple est de renseigner la numérotation manuellement à létape correspondante. Je vous ai joint une capture décran : à la place de\n0032\n, vous pouvez saisir\n0033\n.\nPour tout nouvel échantillon créé cette année, vous ne rencontrerez plus de problème. En revanche, pour les échantillons de lannée précédente, une saisie manuelle restera nécessaire.\nJe reste disponible pour toute discussion téléphonique. Nhésitez pas à me communiquer un numéro et un créneau pour vous joindre.\nJe reste à votre entière disposition pour toute information complémentaire.\nCordialement,\n---\nSupport technique\n\n- image.png (image/png) [ID: 144893]\n\n---\n"
}
],
"date_d'extraction": "16/04/2025 15:12:11",
"répertoire": "output/ticket_T11089/T11089_20250416_151202",
"messages_raw_reference": "output/ticket_T11089/T11089_20250416_151202/messages_raw.json"
}

View File

@ -0,0 +1,113 @@
# Ticket T11089: Problème création feuille paillasse béton
## Informations du ticket
- **id**: 11068
- **code**: T11089
- **name**: Problème création feuille paillasse béton
- **project_name**: Demandes
- **stage_name**: Clôturé
- **user_id**:
- **partner_id/email_from**: CONSEIL DEPARTEMENTAL DE LA SARTHE (72), Contact Laboratoire routier, Contact Laboratoire Routier <laboratoire.routier@sarthe.fr>
- **create_date**: 19/03/2025 15:06:44
- **write_date/last modification**: 04/04/2025 08:06:34
- **date_deadline**: 04/04/2025 00:00:00
- **description**:
*Contenu non extractible*
## Messages
### Message 1
**author_id**: Contact Laboratoire routier
**date**: 19/03/2025 15:02:29
**message_type**: E-mail
**subject**: Problème création feuille paillasse béton
**id**: 228002
Bonjour,
Je rencontre un problème pour créer des échantillons d'éprouvettes béton, ci-joint capture d'écran.
J'en ai déjà créé 3 depuis ce matin, sans souci et là, une fois de plus, un beug alors que par défaut c'est BRG LAB qui nous impose ses numéros en suite logique.
je suis donc bloquée et je ne peux plus travailler.
Merci de faire le nécessaire rapidement.
cordialement
Peggy BRIERE
Laborantin routier
Département de la Sarthe
**attachment_ids**:
- création eprouvette béton.PNG (image/png) [ID: 144880]
---
### Message 2
**author_id**: Romuald GRUSON
**date**: 19/03/2025 15:36:17
**message_type**: E-mail
**subject**: Re: [T11089] - Problème création feuille paillasse béton
**id**: 228005
Bonjour
,
Nous constatons bien le dysfonctionnement d'incrémentation sur votre prochain échantillon de béton. Pour y remédier, vous pouvez renseigner manuellement le prélèvement indiqué +1. Après cette action, le dysfonctionnement sera résolu et la numérotation sincrémente correctement.
Je reste à votre entière disposition pour toute information complémentaire.
Cordialement,
---
Support technique
---
### Message 3
**author_id**: Contact Laboratoire routier
**date**: 20/03/2025 06:55:41
**message_type**: E-mail
**subject**: RE: [T11089] - Problème création feuille paillasse béton
**id**: 228011
Bonjour,
Cela ne fonctionne toujours pas même après votre manip.
Merci de faire le nécessaire car nous sommes toujours bloqué !!!!!
cordialement
Peggy BRIERE
Laborantin routier
Département de la Sarthe
---
### Message 4
**author_id**: Romuald GRUSON
**date**: 20/03/2025 08:10:58
**message_type**: Système
**id**: 228032
20/03/2025 09:10 Plusieurs appels non répondu
---
### Message 5
**author_id**: Romuald GRUSON
**date**: 20/03/2025 08:17:59
**message_type**: E-mail
**subject**: Re: [T11089] - Problème création feuille paillasse béton
**id**: 228033
Bonjour
,
Le dysfonctionnement survient lorsqu'un échantillon a été réalisé sur l'année précédente au prélèvement.
La solution la plus simple est de renseigner la numérotation manuellement à létape correspondante. Je vous ai joint une capture décran : à la place de
0032
, vous pouvez saisir
0033
.
Pour tout nouvel échantillon créé cette année, vous ne rencontrerez plus de problème. En revanche, pour les échantillons de lannée précédente, une saisie manuelle restera nécessaire.
Je reste disponible pour toute discussion téléphonique. Nhésitez pas à me communiquer un numéro et un créneau pour vous joindre.
Je reste à votre entière disposition pour toute information complémentaire.
Cordialement,
---
Support technique
**attachment_ids**:
- image.png (image/png) [ID: 144893]
---
## Informations sur l'extraction
- **Date d'extraction**: 16/04/2025 15:12:11
- **Répertoire**: output/ticket_T11089/T11089_20250416_151202

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,148 @@
TICKET: T11089 - Problème création feuille paillasse béton
Date d'extraction: 2025-04-16 15:12:03
Nombre de messages: 10
================================================================================
********************************************************************************
*** MESSAGE TRANSFÉRÉ ***
********************************************************************************
DATE: 2025-03-19 15:02:29
DE: Contact Laboratoire routier
OBJET: Problème création feuille paillasse béton
Bonjour,
Je rencontre un problème pour créer des échantillons d'éprouvettes béton, ci-joint capture d'écran.
J'en ai déjà créé 3 depuis ce matin, sans souci et là, une fois de plus, un beug alors que par défaut c'est BRG LAB qui nous impose ses numéros en suite logique.
je suis donc bloquée et je ne peux plus travailler.
Merci de faire le nécessaire rapidement.
cordialement
Peggy BRIERE
Laborantin routier
Département de la Sarthe
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 15:06:46
DE: OdooBot
--------------------------------------------------------------------------------
********************************************************************************
*** MESSAGE TRANSFÉRÉ ***
********************************************************************************
DATE: 2025-03-19 15:36:17
DE: Romuald GRUSON
OBJET: Re: [T11089] - Problème création feuille paillasse béton
Bonjour
,
Nous constatons bien le dysfonctionnement d'incrémentation sur votre prochain échantillon de béton. Pour y remédier, vous pouvez renseigner manuellement le prélèvement indiqué +1. Après cette action, le dysfonctionnement sera résolu et la numérotation sincrémente correctement.
Je reste à votre entière disposition pour toute information complémentaire.
Cordialement,
---
Support technique
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-19 15:36:26
DE: Romuald GRUSON
--------------------------------------------------------------------------------
********************************************************************************
*** MESSAGE TRANSFÉRÉ ***
********************************************************************************
DATE: 2025-03-20 06:55:41
DE: Contact Laboratoire routier
OBJET: RE: [T11089] - Problème création feuille paillasse béton
Bonjour,
Cela ne fonctionne toujours pas même après votre manip.
Merci de faire le nécessaire car nous sommes toujours bloqué !!!!!
cordialement
Peggy BRIERE
Laborantin routier
Département de la Sarthe
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-20 07:38:04
DE: Romuald GRUSON
--------------------------------------------------------------------------------
DATE: 2025-03-20 08:10:58
DE: Romuald GRUSON
20/03/2025 09:10 Plusieurs appels non répondu
--------------------------------------------------------------------------------
********************************************************************************
*** MESSAGE TRANSFÉRÉ ***
********************************************************************************
DATE: 2025-03-20 08:17:59
DE: Romuald GRUSON
OBJET: Re: [T11089] - Problème création feuille paillasse béton
Bonjour
,
Le dysfonctionnement survient lorsqu'un échantillon a été réalisé sur l'année précédente au prélèvement.
La solution la plus simple est de renseigner la numérotation manuellement à létape correspondante. Je vous ai joint une capture décran : à la place de
0032
, vous pouvez saisir
0033
.
Pour tout nouvel échantillon créé cette année, vous ne rencontrerez plus de problème. En revanche, pour les échantillons de lannée précédente, une saisie manuelle restera nécessaire.
Je reste disponible pour toute discussion téléphonique. Nhésitez pas à me communiquer un numéro et un créneau pour vous joindre.
Je reste à votre entière disposition pour toute information complémentaire.
Cordialement,
---
Support technique
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-03-20 08:18:04
DE: Romuald GRUSON
--------------------------------------------------------------------------------
********************************************************************************
*** CHANGEMENT D'ÉTAT ***
********************************************************************************
DATE: 2025-04-04 08:06:34
DE: Romuald GRUSON
--------------------------------------------------------------------------------

Some files were not shown because too many files have changed in this diff Show More