diff --git a/output/ticket_T11067/all_messages.json b/output/ticket_T11067/all_messages.json deleted file mode 100644 index 312095e..0000000 --- a/output/ticket_T11067/all_messages.json +++ /dev/null @@ -1,83 +0,0 @@ -[ - { - "id": 228803, - "body": "", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "date": "2025-04-02 07:16:48" - }, - { - "id": 227733, - "body": "", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "date": "2025-03-18 14:19:29" - }, - { - "id": 227732, - "body": "", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "date": "2025-03-18 14:19:29" - }, - { - "id": 227731, - "body": "Bonjour,Effectivement, il y a une anomalie lors du changement du nom d'un poste de production. Les mises à jour déployées ce soir et demain devraient vous permettre d’effectuer cette modification. Pour cela, il faut éditer le nom du poste de production d’enrobée, l’enregistrer dans la fiche générale, puis cliquer sur la petite flèche à droite du nom et le modifier.Je reste à votre entière disposition pour toute information complémentaire.", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "date": "2025-03-18 14:18:51" - }, - { - "id": 227730, - "body": "", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "date": "2025-03-18 13:42:15" - }, - { - "id": 227728, - "body": "", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "date": "2025-03-18 13:42:04" - }, - { - "id": 227726, - "body": "", - "author_id": [ - 2, - "OdooBot" - ], - "date": "2025-03-18 13:22:28" - }, - { - "id": 227725, - "body": "Bonjour, 3 centrales d’enrobage ont changé de nom. Comment faire ce changement sur BRG-LAB ? (ici ARMOR ENROBÉS devient BREIZH ENROBÉS sur 3 sites) ", - "author_id": [ - 5144, - "CONSEIL DEPARTEMENTAL DU MORBIHAN (56), Dominique CARVAL" - ], - "date": "2025-03-18 13:18:31" - }, - { - "id": 227724, - "body": "", - "author_id": [ - 2, - "OdooBot" - ], - "date": "2025-03-18 13:22:28" - } -] \ No newline at end of file diff --git a/output/ticket_T11067/messages_raw.json b/output/ticket_T11067/messages_raw.json deleted file mode 100644 index f9a3332..0000000 --- a/output/ticket_T11067/messages_raw.json +++ /dev/null @@ -1,83 +0,0 @@ -[ - { - "id": 228803, - "body": "", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "date": "2025-04-02 07:16:48" - }, - { - "id": 227733, - "body": "", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "date": "2025-03-18 14:19:29" - }, - { - "id": 227732, - "body": "", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "date": "2025-03-18 14:19:29" - }, - { - "id": 227731, - "body": "

Bonjour,

Effectivement, il y a une anomalie lors du changement du nom d'un poste de production. Les mises à jour déployées ce soir et demain devraient vous permettre d’effectuer cette modification.

\n

Pour cela, il faut éditer le nom du poste de production d’enrobée, l’enregistrer dans la fiche générale, puis cliquer sur la petite flèche à droite du nom et le modifier.

\"image.png\"


Je reste à votre entière disposition pour toute information complémentaire.

Cordialement,

---

Support technique
 

\n

\"CBAO

\n

Afin d'assurer une meilleure traçabilité et vous garantir une prise en charge optimale, nous vous invitons à envoyer vos demandes d'assistance technique à support@cbao.fr
L'objectif du Support Technique est de vous aider : si vous rencontrez une difficulté, ou pour nous soumettre une ou des suggestions d'amélioration de nos logiciels ou de nos méthodes. Notre service est ouvert du lundi au vendredi de 9h à 12h et de 14h à 18h. Dès réception, un technicien prendra en charge votre demande et au besoin vous rappellera.

Confidentialité : Ce courriel contient des informations confidentielles exclusivement réservées au destinataire mentionné. Si vous deviez recevoir cet e-mail par erreur, merci d’en avertir immédiatement l’expéditeur et de le supprimer de votre système informatique. Au cas où vous ne seriez pas destinataire de ce message, veuillez noter que sa divulgation, sa copie ou tout acte en rapport avec la communication du contenu des informations est strictement interdit.

", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "date": "2025-03-18 14:18:51" - }, - { - "id": 227730, - "body": "", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "date": "2025-03-18 13:42:15" - }, - { - "id": 227728, - "body": "", - "author_id": [ - 32165, - "Romuald GRUSON" - ], - "date": "2025-03-18 13:42:04" - }, - { - "id": 227726, - "body": "", - "author_id": [ - 2, - "OdooBot" - ], - "date": "2025-03-18 13:22:28" - }, - { - "id": 227725, - "body": "

\r\n\r\n

\r\n
\r\n

Bonjour,\r\n

\r\n

 

\r\n

3 centrales d’enrobage ont changé de nom.

\r\n

 

\r\n

Comment faire ce changement sur BRG-LAB ?

\r\n

 

\r\n

(ici ARMOR ENROBÉS devient BREIZH ENROBÉS sur 3 sites)

\r\n

 

\r\n

\r\n

 

\r\n

Bonne réception

\r\n

 

\r\n

\"cid:image004.png@01D8D425.0F95E5B0\"

\r\n

 

\r\n

Dominique CARVAL

\r\n

 

\r\n

Responsable du pôle Laboratoire Routier

\r\n

Direction des Infrastructures et des mobilités (DIM)

\r\n

Service d’Appui aux Politiques d’Aménagement / Pôle Laboratoire Routier (SAPA/PLR)

\r\n

115, rue du commerce – 56000 VANNES

\r\n

 

\r\n

tél : 02 97 54 71 14 - mobile : 06 98 32 88 30 –\r\ndominique.carval@morbihan.fr\r\n 

\r\n

 

\r\n

 

\r\n

 

\r\n
\r\n
\r\n
Droit à la déconnexion : Si vous recevez ce message en dehors de vos heures de travail ou pendant vos congés, vous n’êtes pas tenu de répondre immédiatement, sauf en cas d’urgence exceptionnelle.\r\n
\r\nCe message électronique et tous les fichiers attachés qu'il contient peuvent être confidentiels, contenir des données personnelles ou sensibles et être soumis au secret professionnel. Il est destiné exclusivement à l'usage du ou des destinataires. Si vous recevez\r\n ce message par erreur et/ou si vous n'êtes pas le destinataire désigné de ce message, le département du Morbihan vous remercie d'avertir immédiatement l'expéditeur et de le détruire ainsi que toutes les pièces jointes s'y rattachant. La publication, l'usage,\r\n la distribution, l'impression ou la copie non autorisée de ce message et des attachements qu'il contient sont strictement interdits. Tout message électronique est susceptible d'altération.
\r\n\r\n", - "author_id": [ - 5144, - "CONSEIL DEPARTEMENTAL DU MORBIHAN (56), Dominique CARVAL" - ], - "date": "2025-03-18 13:18:31" - }, - { - "id": 227724, - "body": "", - "author_id": [ - 2, - "OdooBot" - ], - "date": "2025-03-18 13:22:28" - } -] \ No newline at end of file diff --git a/output/ticket_T11067/structure.json b/output/ticket_T11067/structure.json deleted file mode 100644 index 6a7bf59..0000000 --- a/output/ticket_T11067/structure.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "date_extraction": "2025-04-03T11:09:41.473063", - "ticket_dir": "output/ticket_T11067", - "fichiers_json": [ - "ticket_info.json", - "messages_raw.json", - "all_messages.json" - ] -} \ No newline at end of file diff --git a/output/ticket_T11067/ticket_info.json b/output/ticket_T11067/ticket_info.json deleted file mode 100644 index bfbc91a..0000000 --- a/output/ticket_T11067/ticket_info.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "id": 11046, - "name": "changement nom centrale d'enrobage", - "description": "


", - "stage_id": "Clôturé" -} \ No newline at end of file diff --git a/utils/ticket_manager2.py b/utils/ticket_manager2.py index f7e529e..218ea26 100644 --- a/utils/ticket_manager2.py +++ b/utils/ticket_manager2.py @@ -7,6 +7,11 @@ from datetime import datetime import re from html import unescape +try: + from bs4 import BeautifulSoup +except ImportError: + BeautifulSoup = None + class TicketManager: def __init__(self, url: str, db: str, username: str, api_key: str): self.url = url @@ -37,7 +42,7 @@ class TicketManager: self.uid = result.get("result", {}).get("uid") self.session_id = response.cookies.get("session_id") return True if self.uid else False - + def _rpc_call(self, endpoint: str, params: Dict[str, Any]) -> Dict[str, Any]: full_url = f"{self.url}{endpoint}" headers = {"Content-Type": "application/json"} @@ -51,15 +56,10 @@ class TicketManager: "model": self.model_name, "method": "read", "args": [[ticket_id]], - "kwargs": {"fields": ["id", "name", "description", "stage_id", "user_id", "partner_id", - "create_date", "write_date", "date_deadline", "priority", - "tag_ids", "code", "project_id"]} + "kwargs": {"fields": ["id", "name", "description", "stage_id", "user_id", "create_date"]} } result = self._rpc_call("/web/dataset/call_kw", params) - - # Afficher le résultat brut pour le débogage - print(f"Réponse brute de l'appel RPC pour le ticket ID {ticket_id} : {result}") - + if isinstance(result, list) and len(result) > 0: return result[0] else: @@ -75,103 +75,82 @@ class TicketManager: }) return messages - def get_ticket_by_code(self, ticket_code: str) -> Dict[str, Any]: - params = { - "model": self.model_name, + def get_ticket_attachments(self, ticket_id: int) -> List[Dict[str, Any]]: + attachments = self._rpc_call("/web/dataset/call_kw", { + "model": "ir.attachment", "method": "search_read", - "args": [[["code", "=", ticket_code]]], - "kwargs": {"fields": ["id", "name", "description", "stage_id", "user_id", - "partner_id", "create_date", "write_date"], "limit": 1} - } - - print(f"Recherche du ticket avec code: {ticket_code}") - result = self._rpc_call("/web/dataset/call_kw", params) - - if result and len(result) > 0: - print(f"Ticket trouvé avec le code {ticket_code}: ID={result[0]['id']}") - return result[0] - else: - print(f"Aucun ticket trouvé avec le code {ticket_code}") - return {} - + "args": [[["res_id", "=", ticket_id], ["res_model", "=", self.model_name]]], + "kwargs": {"fields": ["id", "name", "datas"]} + }) + return attachments + def save_json(self, data: Any, path: str): with open(path, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) + def clean_html(self, html_content: str) -> str: + if BeautifulSoup: + soup = BeautifulSoup(html_content, "html.parser") + text = soup.get_text() + else: + text = re.sub(r'<.*?>', '', html_content) + + text = unescape(text) + text = re.sub(r'\s+', ' ', text).strip() + + return text + def extract_ticket_data(self, ticket_id: int, output_dir: str): os.makedirs(output_dir, exist_ok=True) ticket_data = self.get_ticket(ticket_id) - # Vérifier si le ticket a bien été trouvé if not ticket_data or "id" not in ticket_data: - print(f"Impossible d'extraire les données pour le ticket ID {ticket_id}") - return {"error": "Ticket non trouvé", "ticket_info": None, "messages_file": None, "ticket_data_file": None, "attachments": []} + print(f"Erreur: Ticket non trouvé.") + return - ticket_info = { - "id": ticket_data["id"], - "name": ticket_data["name"], - "description": ticket_data.get("description", ""), - "stage_id": ticket_data.get("stage_id", ["", ""])[1] if ticket_data.get("stage_id") else "Non défini" - } - - self.save_json(ticket_info, os.path.join(output_dir, "ticket_info.json")) + self.save_json(ticket_data, os.path.join(output_dir, "ticket_info.json")) messages = self.get_ticket_messages(ticket_id) + cleaned_messages = [] - # Sauvegarde brute des messages - self.save_json(messages, os.path.join(output_dir, "messages_raw.json")) + for msg in messages: + cleaned_messages.append({ + "message_id": msg["id"], + "sender": msg["author_id"][1] if msg["author_id"] else "Unknown", + "timestamp": msg["date"], + "content": self.clean_html(msg["body"]) + }) - # Nettoyage des messages - cleaned_messages = self._clean_messages(messages) self.save_json(cleaned_messages, os.path.join(output_dir, "all_messages.json")) - # Génération de structure.json + attachments = self.get_ticket_attachments(ticket_id) + attachment_list = [] + + for attachment in attachments: + if "datas" in attachment and attachment["datas"]: + file_name = f"{attachment['id']}_{attachment['name']}" + file_path = os.path.join(output_dir, "attachments", file_name) + os.makedirs(os.path.dirname(file_path), exist_ok=True) + + with open(file_path, "wb") as f: + f.write(base64.b64decode(attachment["datas"])) + + attachment_list.append({ + "id": attachment["id"], + "name": attachment["name"], + "file_path": file_path + }) + + self.save_json(attachment_list, os.path.join(output_dir, "attachments_info.json")) + structure = { "date_extraction": datetime.now().isoformat(), "ticket_dir": output_dir, "fichiers_json": [ "ticket_info.json", - "messages_raw.json", - "all_messages.json" + "all_messages.json", + "attachments_info.json" ] } self.save_json(structure, os.path.join(output_dir, "structure.json")) - - return { - "ticket_info": os.path.join(output_dir, "ticket_info.json"), - "messages_file": os.path.join(output_dir, "all_messages.json"), - "ticket_data_file": os.path.join(output_dir, "structure.json"), - "attachments": [] # Si vous implémentez la gestion des pièces jointes - } - - def _clean_messages(self, messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]: - signatures = [ - r'Droit à la déconnexion.*', - r'Ce message électronique et tous les fichiers attachés.*', - r'Direction des Infrastructures.*', - r'Service d\'Appui aux Politiques d\'Aménagement.*', - r'tél :.*', - r'mobile :.*', - r'email :.*', - r'Cordialement,.*', - r'Bonne réception.*', - r'---.*' - ] - - cleaned_messages = [] - for msg in messages: - body = msg.get("body", "") - body = re.sub(r'<.*?>', '', body) - body = unescape(body) - body = re.sub(r'\s+', ' ', body).strip() - - # Supprime les signatures courantes - for signature in signatures: - body = re.sub(signature, '', body, flags=re.IGNORECASE | re.DOTALL) - - msg["body"] = body - cleaned_messages.append(msg) - - return cleaned_messages -