llm_ticket3/odoo/retrieve_tickets_batch.py
2025-04-09 16:13:20 +02:00

363 lines
12 KiB
Python

#!/usr/bin/env python3
"""
Script pour extraire des lots de tickets Odoo par critères (projet, statut, etc.).
Ce script permet d'automatiser la récupération de nombreux tickets en évitant
de recharger des tickets déjà traités.
"""
import os
import sys
import json
import logging
import argparse
from datetime import datetime
from .auth_manager import AuthManager
from .ticket_manager import TicketManager
from .batch_ticket_manager import BatchTicketManager
from .retrieve_ticket import load_config
from core.utils import setup_logging, log_separator
def retrieve_tickets_batch(domain=None, limit=50, offset=0, output=None, config_file="config.json",
verbose=False, skip_existing=True):
"""
Extrait un lot de tickets répondant à des critères spécifiques.
Args:
domain: Liste de critères de recherche au format Odoo
ex: [["project_id", "=", 1], ["stage_id", "=", 5]]
limit: Nombre maximal de tickets à extraire
offset: Index de départ pour la pagination
output: Répertoire de sortie
config_file: Chemin vers le fichier de configuration
verbose: Mode verbeux pour les logs
skip_existing: Ignorer les tickets déjà extraits
Returns:
Dictionnaire avec le résultat de l'opération ou None en cas d'erreur
"""
config = load_config(config_file)
# Si config est vide, initialiser avec des valeurs par défaut
if not config:
logging.error("Impossible de charger la configuration, utilisation des valeurs par défaut")
config = {"odoo": {}, "output_dir": "output"}
# Configurer la journalisation
log_level = logging.DEBUG if verbose else logging.INFO
setup_logging(log_level, "retrieve_tickets_batch.log")
# Extraire les informations de connexion
odoo_config = config.get("odoo", {})
url = odoo_config.get("url")
db = odoo_config.get("db")
username = odoo_config.get("username")
api_key = odoo_config.get("api_key")
if not all([url, db, username, api_key]):
logging.error("Informations de connexion Odoo manquantes dans le fichier de configuration")
return None
# Définir le répertoire de sortie
base_output_dir = output or config.get("output_dir", "output")
logging.info(f"Démarrage de l'extraction par lot avec les critères: {domain}")
logging.info(f"Limite: {limit} tickets, offset: {offset}")
log_separator()
try:
# Initialiser les gestionnaires
auth_manager = AuthManager(
url=url,
db=db,
username=username,
api_key=api_key
)
if not auth_manager.login():
logging.error("Échec de l'authentification à Odoo")
return None
# Initialiser les gestionnaires
ticket_manager = TicketManager(auth_manager)
batch_manager = BatchTicketManager(ticket_manager)
# Vérifier combien de tickets correspondent aux critères
total_count = batch_manager.get_ticket_count(domain)
logging.info(f"Nombre total de tickets correspondant aux critères: {total_count}")
if total_count == 0:
logging.warning("Aucun ticket ne correspond aux critères spécifiés")
return {"status": "warning", "message": "Aucun ticket ne correspond aux critères"}
# Extraire les tickets par lot
result = batch_manager.extract_tickets_batch(
domain=domain,
limit=limit,
offset=offset,
base_output_dir=base_output_dir,
skip_existing=skip_existing
)
# Afficher le résumé
log_separator()
logging.info(f"Extraction par lot terminée")
logging.info(f"Tickets traités: {result.get('processed', 0)}")
logging.info(f"Tickets ignorés: {result.get('skipped', 0)}")
logging.info(f"Répertoire: {result.get('batch_dir', '')}")
log_separator()
return result
except Exception as e:
logging.exception(f"Une erreur est survenue: {e}")
return None
def list_projects(config_file="config.json"):
"""
Liste tous les projets disponibles dans Odoo.
Args:
config_file: Chemin vers le fichier de configuration
Returns:
Liste des projets ou None en cas d'erreur
"""
config = load_config(config_file)
# Extraire les informations de connexion
odoo_config = config.get("odoo", {})
url = odoo_config.get("url")
db = odoo_config.get("db")
username = odoo_config.get("username")
api_key = odoo_config.get("api_key")
if not all([url, db, username, api_key]):
print("Informations de connexion Odoo manquantes dans le fichier de configuration")
return None
try:
# Initialiser les gestionnaires
auth_manager = AuthManager(
url=url,
db=db,
username=username,
api_key=api_key
)
if not auth_manager.login():
print("Échec de l'authentification à Odoo")
return None
# Récupérer la liste des projets
ticket_manager = TicketManager(auth_manager)
batch_manager = BatchTicketManager(ticket_manager)
projects = batch_manager.get_projects()
if not projects:
print("Aucun projet trouvé")
return None
print("\nListe des projets disponibles:")
print("-" * 50)
for project in projects:
print(f"ID: {project['id']}, Nom: {project['name']}")
print("-" * 50)
return projects
except Exception as e:
print(f"Une erreur est survenue: {e}")
return None
def list_stages(config_file="config.json"):
"""
Liste tous les statuts (étapes) disponibles dans Odoo.
Args:
config_file: Chemin vers le fichier de configuration
Returns:
Liste des étapes ou None en cas d'erreur
"""
config = load_config(config_file)
# Extraire les informations de connexion
odoo_config = config.get("odoo", {})
url = odoo_config.get("url")
db = odoo_config.get("db")
username = odoo_config.get("username")
api_key = odoo_config.get("api_key")
if not all([url, db, username, api_key]):
print("Informations de connexion Odoo manquantes dans le fichier de configuration")
return None
try:
# Initialiser les gestionnaires
auth_manager = AuthManager(
url=url,
db=db,
username=username,
api_key=api_key
)
if not auth_manager.login():
print("Échec de l'authentification à Odoo")
return None
# Récupérer la liste des étapes
ticket_manager = TicketManager(auth_manager)
batch_manager = BatchTicketManager(ticket_manager)
stages = batch_manager.get_stages()
if not stages:
print("Aucune étape trouvée")
return None
print("\nListe des étapes disponibles:")
print("-" * 50)
for stage in stages:
print(f"ID: {stage['id']}, Nom: {stage['name']}")
print("-" * 50)
return stages
except Exception as e:
print(f"Une erreur est survenue: {e}")
return None
def parse_domain(domain_str):
"""
Convertit une chaîne de critères en domaine Odoo.
Format attendu: "field1:op1:value1;field2:op2:value2"
Exemple: "project_id:=:1;stage_id:=:5"
Args:
domain_str: Chaîne de critères
Returns:
Liste de critères au format Odoo
"""
if not domain_str:
return []
domain = []
criteria = domain_str.split(";")
for criterion in criteria:
if not criterion:
continue
parts = criterion.split(":")
if len(parts) != 3:
print(f"Format invalide pour le critère: {criterion}")
continue
field, operator, value = parts
# Convertir value en entier si possible
try:
if value.isdigit():
value = int(value)
elif value.lower() == "true":
value = True
elif value.lower() == "false":
value = False
except:
pass
domain.append([field, operator, value])
return domain
def parse_arguments():
parser = argparse.ArgumentParser(description="Récupère des tickets Odoo par lots selon des critères.")
subparsers = parser.add_subparsers(dest="command", help="Commande à exécuter")
# Commande pour extraire un lot de tickets
batch_parser = subparsers.add_parser("batch", help="Extrait un lot de tickets")
batch_parser.add_argument("--domain", "-d", help="Critères de recherche (format: field1:op1:value1;field2:op2:value2)")
batch_parser.add_argument("--project", "-p", type=int, help="ID du projet")
batch_parser.add_argument("--stage", "-s", type=int, help="ID de l'étape/statut")
batch_parser.add_argument("--limit", "-l", type=int, default=50, help="Nombre maximum de tickets à extraire")
batch_parser.add_argument("--offset", "-o", type=int, default=0, help="Index de départ pour la pagination")
batch_parser.add_argument("--output", help="Répertoire de sortie")
batch_parser.add_argument("--include-existing", action="store_true", help="Inclure les tickets déjà extraits")
batch_parser.add_argument("--config", "-c", default="config.json", help="Fichier de configuration")
batch_parser.add_argument("--verbose", "-v", action="store_true", help="Mode verbeux")
# Commande pour lister les projets
projects_parser = subparsers.add_parser("projects", help="Liste les projets disponibles")
projects_parser.add_argument("--config", "-c", default="config.json", help="Fichier de configuration")
# Commande pour lister les étapes
stages_parser = subparsers.add_parser("stages", help="Liste les étapes/statuts disponibles")
stages_parser.add_argument("--config", "-c", default="config.json", help="Fichier de configuration")
# Commande pour extraire un ticket unique (compatibilité avec retrieve_ticket.py)
ticket_parser = subparsers.add_parser("ticket", help="Extrait un ticket unique par son code")
ticket_parser.add_argument("ticket_code", help="Code du ticket à extraire")
ticket_parser.add_argument("--output", help="Répertoire de sortie")
ticket_parser.add_argument("--config", "-c", default="config.json", help="Fichier de configuration")
ticket_parser.add_argument("--verbose", "-v", action="store_true", help="Mode verbeux")
return parser.parse_args()
def main():
args = parse_arguments()
if args.command == "projects":
list_projects(args.config)
elif args.command == "stages":
list_stages(args.config)
elif args.command == "ticket":
# Compatibilité avec retrieve_ticket.py
from .retrieve_ticket import retrieve_ticket
result = retrieve_ticket(
ticket_code=args.ticket_code,
output=args.output,
config_file=args.config,
verbose=args.verbose
)
if not result:
sys.exit(1)
elif args.command == "batch":
# Construire le domaine à partir des options
domain = []
if args.domain:
domain = parse_domain(args.domain)
# Ajouter project_id et stage_id si spécifiés
if args.project:
domain.append(["project_id", "=", args.project])
if args.stage:
domain.append(["stage_id", "=", args.stage])
result = retrieve_tickets_batch(
domain=domain,
limit=args.limit,
offset=args.offset,
output=args.output,
config_file=args.config,
verbose=args.verbose,
skip_existing=not args.include_existing
)
if not result or result.get("status") == "error":
sys.exit(1)
else:
# Aucune commande spécifiée, afficher l'aide
parser = argparse.ArgumentParser(description="Récupère des tickets Odoo par lots selon des critères.")
parser.print_help()
sys.exit(1)
if __name__ == "__main__":
main()