Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| """ | |
| Interface Gradio simplifiée pour Odoo ERP avec fonctions CRM natives | |
| """ | |
| import gradio as gr | |
| import logging | |
| import json | |
| import sys | |
| import os | |
| # Ajout du répertoire src au path | |
| sys.path.insert(0, os.path.abspath('.')) | |
| try: | |
| # Import de la configuration | |
| import config | |
| # Import des fonctions CRM natives | |
| import crm_gradio_tools | |
| # Import des fonctions Sales natives | |
| import sales_gradio_tools | |
| # Import des fonctions Modal ML | |
| import modal_gradio_wrapper | |
| except ImportError as e: | |
| print(f"❌ Erreur d'importation: {e}") | |
| sys.exit(1) | |
| # Configuration logging simple | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| # ============================================================================= | |
| # FONCTIONS DE L'INTERFACE GRADIO (Logique UI) | |
| # ============================================================================= | |
| async def test_connection_only(url: str, database: str, username: str, password: str): | |
| """TESTE uniquement la connexion sans sauvegarder""" | |
| try: | |
| if not all([url, database, username, password]): | |
| return [{"role": "assistant", "content": "❌ Tous les champs sont requis"}] | |
| # Test temporaire | |
| temp_client = config.SimpleOdooClient() | |
| result = temp_client.connect(url.strip(), database.strip(), username.strip(), password) | |
| if result["success"]: | |
| return [{"role": "assistant", "content": f"✅ **Test connexion réussi !**\n\n🌐 URL: {url}\n🗄️ Base: {database}\n👤 Utilisateur: {username}\n📋 Version: {result.get('version', 'N/A')}\n\n⚠️ **Credentials non sauvegardés** - Cliquez 'Enregistrer' pour activer les fonctions CRM."}] | |
| else: | |
| return [{"role": "assistant", "content": f"❌ Erreur de connexion: {result['error']}"}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Exception: {str(e)}"}] | |
| async def save_credentials(url: str, database: str, username: str, password: str): | |
| """SAUVEGARDE les credentials et connecte le client global""" | |
| try: | |
| if not all([url, database, username, password]): | |
| return [{"role": "assistant", "content": "❌ Tous les champs sont requis"}] | |
| # ✅ CONNEXION ET SAUVEGARDE DU CLIENT GLOBAL | |
| result = config.client.connect(url.strip(), database.strip(), username.strip(), password) | |
| if result["success"]: | |
| # ✅ SAUVEGARDE EN MÉMOIRE ET FICHIER | |
| config.stored_credentials.update({ | |
| "url": url.strip(), | |
| "database": database.strip(), | |
| "username": username.strip(), | |
| "password": password | |
| }) | |
| # ✅ PERSISTANCE FICHIER | |
| config.save_credentials_to_file(url.strip(), database.strip(), username.strip(), password) | |
| success_msg = f"""✅ **Credentials sauvegardés et connecté !** | |
| 🌐 **URL**: {url} | |
| 🗄️ **Base**: {database} | |
| 👤 **Utilisateur**: {username} | |
| 📋 **Version**: {result.get('version', 'N/A')} | |
| 💾 **Persistance**: Fichier `odoo_config.json` créé | |
| 🤖 **MCP activé** - Claude peut maintenant accéder à votre Odoo ! | |
| 🔥 **CRM natif** - Fonctions d'analyse intelligente disponibles !""" | |
| return [{"role": "assistant", "content": success_msg}] | |
| else: | |
| return [{"role": "assistant", "content": f"❌ Erreur de connexion: {result['error']}"}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Exception: {str(e)}"}] | |
| async def load_saved_credentials(): | |
| """Charge les credentials sauvegardés""" | |
| config.stored_credentials = config.load_credentials_from_file() | |
| if all(config.stored_credentials.values()): | |
| # Tentative de connexion automatique | |
| result = config.client.connect( | |
| config.stored_credentials["url"], | |
| config.stored_credentials["database"], | |
| config.stored_credentials["username"], | |
| config.stored_credentials["password"] | |
| ) | |
| if result["success"]: | |
| return ( | |
| config.stored_credentials["url"], | |
| config.stored_credentials["database"], | |
| config.stored_credentials["username"], | |
| config.stored_credentials["password"], | |
| [{"role": "assistant", "content": f"✅ **Credentials chargés et connecté !**\n\n🌐 URL: {config.stored_credentials['url']}\n🗄️ Base: {config.stored_credentials['database']}\n👤 Utilisateur: {config.stored_credentials['username']}\n🔥 **CRM natif disponible !**"}] | |
| ) | |
| else: | |
| return ( | |
| config.stored_credentials["url"], | |
| config.stored_credentials["database"], | |
| config.stored_credentials["username"], | |
| config.stored_credentials["password"], | |
| [{"role": "assistant", "content": f"⚠️ **Credentials chargés mais connexion échouée**: {result['error']}"}] | |
| ) | |
| else: | |
| return ("", "", "", "", [{"role": "assistant", "content": "📂 Aucun credential sauvegardé trouvé"}]) | |
| async def search_records_simple(model: str, domain_text: str, fields_text: str, limit: int): | |
| """Recherche d'enregistrements simple""" | |
| try: | |
| if not config.client.is_connected(): | |
| return [{"role": "assistant", "content": "❌ Pas connecté à Odoo - Cliquez 'Enregistrer' d'abord"}] | |
| # Parse domaine | |
| domain = [] | |
| if domain_text.strip(): | |
| try: | |
| domain = eval(domain_text.strip()) | |
| except: | |
| return [{"role": "assistant", "content": "❌ Format de domaine invalide. Utilisez: [['field', '=', 'value']]"}] | |
| # Parse champs | |
| fields = [f.strip() for f in fields_text.split(',') if f.strip()] if fields_text else [] | |
| # Recherche | |
| records = config.client.search_read(model, domain, fields, limit) | |
| if records: | |
| result_text = f"✅ **{len(records)} enregistrements trouvés dans {model}**\n\n" | |
| for i, record in enumerate(records[:3]): | |
| result_text += f"**{i+1}.** ID: {record.get('id', 'N/A')}" | |
| if 'name' in record: | |
| result_text += f" | Nom: {record['name']}" | |
| if 'email' in record: | |
| result_text += f" | Email: {record['email']}" | |
| result_text += "\n" | |
| if len(records) > 3: | |
| result_text += f"\n... et {len(records) - 3} autres enregistrements" | |
| return [{"role": "assistant", "content": result_text}] | |
| else: | |
| return [{"role": "assistant", "content": f"⚠️ Aucun enregistrement trouvé dans {model}"}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur: {str(e)}"}] | |
| async def create_record_simple(model: str, values_json: str): | |
| """Création d'enregistrement simple""" | |
| try: | |
| if not config.client.is_connected(): | |
| return [{"role": "assistant", "content": "❌ Pas connecté à Odoo - Cliquez 'Enregistrer' d'abord"}] | |
| try: | |
| values = json.loads(values_json) | |
| except json.JSONDecodeError: | |
| return [{"role": "assistant", "content": "❌ JSON invalide"}] | |
| record_id = config.client.create(model, values) | |
| return [{"role": "assistant", "content": f"✅ Enregistrement créé avec l'ID: **{record_id}** dans {model}"}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur: {str(e)}"}] | |
| def clear_workspace(): | |
| """Nettoie l'espace de travail""" | |
| config.stored_credentials.clear() | |
| config.stored_credentials.update({"url": "", "database": "", "username": "", "password": ""}) | |
| return gr.update(value=""), gr.update(value=""), gr.update(value=""), gr.update(value=""), [] | |
| # ============================================================================= | |
| # FONCTIONS CRM NATIVES POUR GRADIO | |
| # ============================================================================= | |
| async def get_crm_stats(): | |
| """Récupère les statistiques CRM natives""" | |
| try: | |
| result = crm_gradio_tools.get_crm_statistics() | |
| return [{"role": "assistant", "content": result}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur CRM: {str(e)}"}] | |
| async def analyze_leads(domain_filter: str, limit: int): | |
| """Analyse avancée des leads native""" | |
| try: | |
| result = crm_gradio_tools.analyze_leads_advanced(domain_filter, limit) | |
| return [{"role": "assistant", "content": result}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur analyse: {str(e)}"}] | |
| async def monitor_crm(time_window: int, threshold: float): | |
| """Monitoring CRM natif""" | |
| try: | |
| result = crm_gradio_tools.monitor_crm_performance(time_window, threshold) | |
| return [{"role": "assistant", "content": result}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur monitoring: {str(e)}"}] | |
| async def search_leads(name: str, min_revenue: float, stage: str, limit: int): | |
| """Recherche des leads native""" | |
| try: | |
| result = crm_gradio_tools.search_leads_by_criteria(name, min_revenue, stage, limit) | |
| return [{"role": "assistant", "content": result}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur recherche: {str(e)}"}] | |
| async def get_crm_info(): | |
| """Affiche les informations sur les fonctions CRM""" | |
| try: | |
| result = crm_gradio_tools.get_crm_tools_info() | |
| return [{"role": "assistant", "content": result}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur info: {str(e)}"}] | |
| # ============================================================================= | |
| # FONCTIONS SALES NATIVES POUR GRADIO | |
| # ============================================================================= | |
| async def get_sales_stats(): | |
| """Récupère les statistiques Sales natives""" | |
| try: | |
| result = await sales_gradio_tools.get_sales_statistics() | |
| return [{"role": "assistant", "content": result}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur Sales: {str(e)}"}] | |
| async def analyze_quotations(domain_filter: str, limit: int): | |
| """Analyse avancée des devis native""" | |
| try: | |
| result = await sales_gradio_tools.analyze_quotations_advanced(domain_filter, limit) | |
| return [{"role": "assistant", "content": result}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur analyse devis: {str(e)}"}] | |
| async def send_quotation_email(order_id: int, subject: str, body: str): | |
| """Envoi d'email de devis natif""" | |
| try: | |
| result = await sales_gradio_tools.send_quotation_email_gradio(order_id, subject, body) | |
| return [{"role": "assistant", "content": result}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur envoi email: {str(e)}"}] | |
| async def search_sales_orders_wrapper(name: str, min_amount: float, state: str, limit: int): | |
| """Recherche des commandes de vente native""" | |
| try: | |
| result = await sales_gradio_tools.search_sales_orders(name, min_amount, state, limit) | |
| return [{"role": "assistant", "content": result}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur recherche commandes: {str(e)}"}] | |
| async def monitor_sales(time_window: int, threshold: float): | |
| """Monitoring Sales natif""" | |
| try: | |
| result = await sales_gradio_tools.monitor_sales_performance(time_window, threshold) | |
| return [{"role": "assistant", "content": result}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur monitoring sales: {str(e)}"}] | |
| async def get_sales_info(): | |
| """Affiche les informations sur les fonctions Sales""" | |
| try: | |
| result = await sales_gradio_tools.get_sales_tools_info() | |
| return [{"role": "assistant", "content": result}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur info sales: {str(e)}"}] | |
| # ============================================================================= | |
| # FONCTIONS MODAL ML POUR GRADIO | |
| # ============================================================================= | |
| async def train_modal_model(num_leads: int): | |
| """Entraîne le modèle Modal ML""" | |
| try: | |
| result_msg, status_msg = modal_gradio_wrapper.gradio_train_model(num_leads) | |
| return [{"role": "assistant", "content": result_msg}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur entraînement Modal: {str(e)}"}] | |
| async def predict_modal_lead(name: str, industry: str, company_size: str, | |
| budget_range: str, urgency: str, source: str, | |
| expected_revenue: float, response_time: float): | |
| """Prédiction Modal pour un lead""" | |
| try: | |
| result = modal_gradio_wrapper.gradio_predict_lead( | |
| name, industry, company_size, budget_range, | |
| urgency, source, expected_revenue, response_time | |
| ) | |
| return [{"role": "assistant", "content": result}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur prédiction Modal: {str(e)}"}] | |
| async def get_modal_status(): | |
| """Statut du modèle Modal""" | |
| try: | |
| result = modal_gradio_wrapper.gradio_get_model_status() | |
| return [{"role": "assistant", "content": result}] | |
| except Exception as e: | |
| return [{"role": "assistant", "content": f"❌ Erreur statut Modal: {str(e)}"}] | |
| # Interface Gradio améliorée | |
| theme = gr.themes.Soft( | |
| primary_hue="blue", | |
| secondary_hue="slate", | |
| neutral_hue="gray", | |
| ) | |
| with gr.Blocks(title="Interface Odoo CRM & Sales", theme=theme) as demo: | |
| gr.Markdown(""" | |
| # 🚀 Interface Odoo CRM & Sales | |
| **Interface simplifiée pour la gestion et l'analyse de votre CRM et Sales Odoo.** | |
| --- | |
| """) | |
| # ======================================================================== | |
| # SECTION CONNEXION | |
| # ======================================================================== | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| gr.Markdown("### 🔐 Connexion Odoo") | |
| url_input = gr.Textbox( | |
| label="🌐 URL Odoo", | |
| placeholder="https://votre-instance.odoo.com", | |
| value=config.ODOO_URL | |
| ) | |
| db_input = gr.Textbox( | |
| label="🗄️ Base de données", | |
| placeholder="votre-db", | |
| value=config.ODOO_DB | |
| ) | |
| username_input = gr.Textbox( | |
| label="👤 Utilisateur", | |
| placeholder="[email protected]", | |
| value=config.ODOO_USERNAME | |
| ) | |
| password_input = gr.Textbox( | |
| label="🔒 Mot de passe", | |
| type="password", | |
| value=config.ODOO_PASSWORD | |
| ) | |
| with gr.Row(): | |
| clear_btn = gr.Button("🗑️ Effacer", variant="secondary") | |
| load_btn = gr.Button("📂 Charger", variant="secondary") | |
| test_btn = gr.Button("🧪 Tester", variant="secondary") | |
| save_btn = gr.Button("💾 Enregistrer", variant="primary") | |
| with gr.Column(scale=1): | |
| chatbot = gr.Chatbot( | |
| label="📋 Statut de connexion", | |
| type="messages", | |
| height=300, | |
| avatar_images=(None, "🤖") | |
| ) | |
| # ======================================================================== | |
| # SECTIONS FONCTIONNELLES - ONGLETS | |
| # ======================================================================== | |
| with gr.Tabs(): | |
| # ==================================================================== | |
| # ONGLET CRM | |
| # ==================================================================== | |
| with gr.TabItem("📊 CRM"): | |
| gr.Markdown("### 🎯 Fonctions CRM Natives") | |
| with gr.Row(): | |
| with gr.Column(): | |
| crm_stats_btn = gr.Button("📊 Statistiques CRM", variant="primary") | |
| crm_info_btn = gr.Button("ℹ️ Info CRM Tools", variant="secondary") | |
| with gr.Column(): | |
| gr.Markdown("**🔍 Analyse Leads**") | |
| leads_domain = gr.Textbox(label="Domaine (JSON)", placeholder="[]", value="[]") | |
| leads_limit = gr.Slider(5, 50, 20, label="Limite") | |
| analyze_leads_btn = gr.Button("🚀 Analyser Leads") | |
| with gr.Column(): | |
| gr.Markdown("**📊 Monitoring**") | |
| monitor_hours = gr.Slider(1, 168, 24, label="Heures") | |
| monitor_threshold = gr.Slider(0.1, 1.0, 0.7, label="Seuil") | |
| monitor_crm_btn = gr.Button("📈 Monitor CRM") | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("**🔍 Recherche Leads**") | |
| search_name = gr.Textbox(label="Nom", placeholder="") | |
| search_revenue = gr.Number(label="Revenue min", value=0) | |
| search_stage = gr.Textbox(label="Étape", placeholder="") | |
| search_limit = gr.Slider(5, 50, 10, label="Limite") | |
| search_leads_btn = gr.Button("🔍 Rechercher") | |
| crm_output = gr.Chatbot(label="💬 Résultats CRM", type="messages", height=400) | |
| # ==================================================================== | |
| # ONGLET SALES | |
| # ==================================================================== | |
| with gr.TabItem("💰 Sales"): | |
| gr.Markdown("### 🎯 Fonctions Sales Natives") | |
| with gr.Row(): | |
| with gr.Column(): | |
| sales_stats_btn = gr.Button("💰 Statistiques Sales", variant="primary") | |
| sales_info_btn = gr.Button("ℹ️ Info Sales Tools", variant="secondary") | |
| with gr.Column(): | |
| gr.Markdown("**📊 Analyse Devis**") | |
| quota_domain = gr.Textbox(label="Domaine (JSON)", placeholder="[]", value="[]") | |
| quota_limit = gr.Slider(5, 100, 20, label="Limite") | |
| analyze_quotas_btn = gr.Button("📋 Analyser Devis") | |
| with gr.Column(): | |
| gr.Markdown("**📧 Email Devis**") | |
| email_order_id = gr.Number(label="ID Commande", value=0) | |
| email_subject = gr.Textbox(label="Sujet", placeholder="") | |
| email_body = gr.Textbox(label="Corps", placeholder="", lines=3) | |
| send_email_btn = gr.Button("📧 Envoyer Email") | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("**🔍 Recherche Commandes**") | |
| order_name = gr.Textbox(label="Nom", placeholder="") | |
| order_amount = gr.Number(label="Montant min", value=0) | |
| order_state = gr.Textbox(label="État", placeholder="") | |
| order_limit = gr.Slider(5, 50, 10, label="Limite") | |
| search_orders_btn = gr.Button("🔍 Rechercher") | |
| with gr.Column(): | |
| gr.Markdown("**📊 Monitoring Sales**") | |
| sales_hours = gr.Slider(1, 168, 24, label="Heures") | |
| sales_threshold = gr.Slider(0.1, 1.0, 0.7, label="Seuil") | |
| monitor_sales_btn = gr.Button("📈 Monitor Sales") | |
| sales_output = gr.Chatbot(label="💬 Résultats Sales", type="messages", height=400) | |
| # ==================================================================== | |
| # ONGLET MODAL ML | |
| # ==================================================================== | |
| with gr.TabItem("🤖 Modal ML"): | |
| gr.Markdown("### 🧠 Intelligence Artificielle Modal") | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("**🎯 Modèle ML**") | |
| modal_status_btn = gr.Button("📊 Statut Modèle", variant="secondary") | |
| num_synthetic_leads = gr.Slider(100, 5000, 1000, label="Leads synthétiques") | |
| train_model_btn = gr.Button("🚀 Entraîner Modèle", variant="primary") | |
| with gr.Column(): | |
| gr.Markdown("**🔮 Prédiction Lead**") | |
| pred_name = gr.Textbox(label="Nom du lead", placeholder="Artisans Bernard") | |
| pred_industry = gr.Dropdown( | |
| choices=["Technology", "Healthcare", "Finance", "Manufacturing", "Retail", "Other"], | |
| label="Secteur", | |
| value="Technology" | |
| ) | |
| pred_company_size = gr.Dropdown( | |
| choices=["Small", "Medium", "Large", "Enterprise"], | |
| label="Taille entreprise", | |
| value="Medium" | |
| ) | |
| with gr.Column(): | |
| gr.Markdown("**💰 Détails Lead**") | |
| pred_budget = gr.Dropdown( | |
| choices=["Low", "Medium", "High", "Very High"], | |
| label="Budget", | |
| value="Medium" | |
| ) | |
| pred_urgency = gr.Dropdown( | |
| choices=["Low", "Medium", "High", "Critical"], | |
| label="Urgence", | |
| value="Medium" | |
| ) | |
| pred_source = gr.Dropdown( | |
| choices=["Website", "Email", "Cold Call", "Referral", "Social Media"], | |
| label="Source", | |
| value="Website" | |
| ) | |
| with gr.Row(): | |
| with gr.Column(): | |
| pred_revenue = gr.Number(label="Revenue attendu (€)", value=15000, minimum=0) | |
| pred_response_time = gr.Number(label="Temps de réponse (h)", value=2.0, minimum=0.1) | |
| predict_btn = gr.Button("🔮 Prédire Conversion", variant="primary") | |
| modal_output = gr.Chatbot(label="💬 Résultats Modal ML", type="messages", height=400) | |
| # ==================================================================== | |
| # ONGLET RECHERCHE SIMPLE | |
| # ==================================================================== | |
| with gr.TabItem("🔍 Recherche"): | |
| gr.Markdown("### 🔍 Recherche Simple Odoo") | |
| with gr.Row(): | |
| with gr.Column(): | |
| model_input = gr.Textbox(label="Modèle", placeholder="crm.lead", value="crm.lead") | |
| domain_input = gr.Textbox(label="Domaine", placeholder="[['name', 'ilike', 'test']]", value="[]") | |
| fields_input = gr.Textbox(label="Champs", placeholder="name,email_from,phone", value="name,email_from,phone") | |
| limit_input = gr.Slider(1, 50, 10, label="Limite") | |
| search_btn = gr.Button("🔍 Rechercher", variant="primary") | |
| with gr.Column(): | |
| gr.Markdown("**➕ Création Simple**") | |
| create_model = gr.Textbox(label="Modèle", placeholder="crm.lead") | |
| create_values = gr.Textbox(label="Valeurs (JSON)", placeholder='{"name": "Test Lead"}', lines=5) | |
| create_btn = gr.Button("➕ Créer", variant="secondary") | |
| search_output = gr.Chatbot(label="💬 Résultats Recherche", type="messages", height=400) | |
| # ======================================================================== | |
| # ÉVÉNEMENTS CONNEXION | |
| # ======================================================================== | |
| # Connexion | |
| test_btn.click( | |
| fn=test_connection_only, | |
| inputs=[url_input, db_input, username_input, password_input], | |
| outputs=chatbot, | |
| queue=True, | |
| ) | |
| save_btn.click( | |
| fn=save_credentials, | |
| inputs=[url_input, db_input, username_input, password_input], | |
| outputs=chatbot, | |
| queue=True, | |
| ) | |
| # Utilitaires | |
| clear_btn.click( | |
| fn=clear_workspace, | |
| inputs=[], | |
| outputs=[url_input, db_input, username_input, password_input, chatbot], | |
| ) | |
| load_btn.click( | |
| fn=load_saved_credentials, | |
| inputs=[], | |
| outputs=[url_input, db_input, username_input, password_input, chatbot], | |
| queue=True, | |
| ) | |
| # ======================================================================== | |
| # ÉVÉNEMENTS CRM | |
| # ======================================================================== | |
| crm_stats_btn.click(fn=get_crm_stats, inputs=[], outputs=crm_output, queue=True) | |
| crm_info_btn.click(fn=get_crm_info, inputs=[], outputs=crm_output, queue=True) | |
| analyze_leads_btn.click(fn=analyze_leads, inputs=[leads_domain, leads_limit], outputs=crm_output, queue=True) | |
| monitor_crm_btn.click(fn=monitor_crm, inputs=[monitor_hours, monitor_threshold], outputs=crm_output, queue=True) | |
| search_leads_btn.click(fn=search_leads, inputs=[search_name, search_revenue, search_stage, search_limit], outputs=crm_output, queue=True) | |
| # ======================================================================== | |
| # ÉVÉNEMENTS SALES | |
| # ======================================================================== | |
| sales_stats_btn.click(fn=get_sales_stats, inputs=[], outputs=sales_output, queue=True) | |
| sales_info_btn.click(fn=get_sales_info, inputs=[], outputs=sales_output, queue=True) | |
| analyze_quotas_btn.click(fn=analyze_quotations, inputs=[quota_domain, quota_limit], outputs=sales_output, queue=True) | |
| send_email_btn.click(fn=send_quotation_email, inputs=[email_order_id, email_subject, email_body], outputs=sales_output, queue=True) | |
| search_orders_btn.click(fn=search_sales_orders_wrapper, inputs=[order_name, order_amount, order_state, order_limit], outputs=sales_output, queue=True) | |
| monitor_sales_btn.click(fn=monitor_sales, inputs=[sales_hours, sales_threshold], outputs=sales_output, queue=True) | |
| # ======================================================================== | |
| # ÉVÉNEMENTS MODAL ML | |
| # ======================================================================== | |
| modal_status_btn.click(fn=get_modal_status, inputs=[], outputs=modal_output, queue=True) | |
| train_model_btn.click(fn=train_modal_model, inputs=[num_synthetic_leads], outputs=modal_output, queue=True) | |
| predict_btn.click(fn=predict_modal_lead, inputs=[pred_name, pred_industry, pred_company_size, pred_budget, pred_urgency, pred_source, pred_revenue, pred_response_time], outputs=modal_output, queue=True) | |
| # ======================================================================== | |
| # ÉVÉNEMENTS RECHERCHE SIMPLE | |
| # ======================================================================== | |
| search_btn.click(fn=search_records_simple, inputs=[model_input, domain_input, fields_input, limit_input], outputs=search_output, queue=True) | |
| create_btn.click(fn=create_record_simple, inputs=[create_model, create_values], outputs=search_output, queue=True) | |
| gr.Markdown(""" | |
| --- | |
| ### 🚀 Guide d'Utilisation | |
| #### 📶 **1. Connexion** | |
| 1. **Remplir** vos informations Odoo | |
| 2. **Tester** la connexion (optionnel) | |
| 3. **Enregistrer** pour activer toutes les fonctions CRM & Sales | |
| #### 📊 **2. Utilisation CRM** | |
| - **Statistiques** : Vue d'ensemble du pipeline | |
| - **Analyse Leads** : Classification intelligente | |
| - **Monitoring** : Surveillance temps réel | |
| - **Recherche** : Filtrage multi-critères | |
| #### 💰 **3. Utilisation Sales** | |
| - **Statistiques** : Métriques commerciales | |
| - **Analyse Devis** : Recommandations d'actions | |
| - **Email Devis** : Envoi personnalisé | |
| - **Recherche** : Gestion des commandes | |
| #### 🤖 **4. Intelligence Artificielle Modal** | |
| - **Statut Modèle** : Vérifier si le modèle ML est entraîné | |
| - **Entraîner Modèle** : Créer un modèle personnalisé (1000+ leads synthétiques) | |
| - **Prédire Conversion** : Analyse IA d'un lead spécifique | |
| - **Classification** : HOT/WARM/COLD avec probabilités avancées | |
| --- | |
| ### 💡 Objectif | |
| **🔥 Interface CRM & Sales native** : | |
| - 📊 Analyse de vos vraies données Odoo | |
| - 🎯 Fonctions CRM et Sales opérationnelles | |
| - 📈 Reporting et statistiques en temps réel | |
| - 📧 Envoi d'emails de devis personnalisés | |
| - 🤖 Intelligence Artificielle Modal pour prédictions | |
| - 🤖 Serveur MCP pour l'intégration IA | |
| --- | |
| """) | |
| if __name__ == "__main__": | |
| print("🚀 Démarrage Interface Odoo CRM & Sales...") | |
| print("📊 Interface native pour l'analyse CRM & Sales") | |
| print("📧 Fonctions d'envoi d'emails intégrées") | |
| print("🤖 Intelligence Artificielle Modal pour prédictions") | |
| print("🤖 Serveur MCP activé pour les outils IA") | |
| demo.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| mcp_server=True, | |
| share=False, | |
| show_error=True | |
| ) |