bemade-addons/helpdesk_sale_order_ai/models/res_config_settings.py
mathis ed9dda9bea [ADD] openwebui_connector, helpdesk_sale_order_ai: AI-powered sales order generation from helpdesk tickets
This commit introduces AI integration for helpdesk tickets to automatically generate sales orders:

- openwebui_connector: New module providing integration with OpenWebUI AI service
  * Configurable API connection (key, base URL, model)
  * AI prompt template system for reusable prompts
  * Uses Claude 3 Sonnet model by default

- helpdesk_sale_order_ai: Extends helpdesk_sale_order with AI capabilities
  * AI-powered analysis of ticket content to suggest products
  * Smart product quantity parsing from various formats
  * Dedicated UI tab for AI suggestions in helpdesk tickets
  * Auto-creation of sales orders with matched products

The integration streamlines the process of converting customer support requests into sales opportunities.
2025-07-15 15:18:01 -04:00

111 lines
5 KiB
Python

# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
import logging
_logger = logging.getLogger(__name__)
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
# We no longer need to define the fields here as they are now defined in the openai_connector module
# This ensures that the settings are always in sync between the two modules
# Override the model field to use our selection method
openai_model = fields.Selection(
selection='_get_openwebui_models',
string='AI Model',
help='Model to use for AI API calls',
default='anthropic.claude-3-7-sonnet-latest',
config_parameter='openai.model',
)
# Add a field to select the prompt template directly
# In Odoo 18, we need to ensure this field is properly defined
helpdesk_ai_prompt_template_id = fields.Many2one(
'openwebui.prompt.template',
domain="[('template_type', '=', 'helpdesk')]",
string='Default AI Prompt Template',
help='Default template for the prompt sent to the AI.',
ondelete='set null', # This helps avoid constraint errors
)
@api.model
def get_values(self):
"""Get values for the settings form"""
res = super(ResConfigSettings, self).get_values()
# Get the template ID from the system parameter
IrConfigParam = self.env['ir.config_parameter'].sudo()
template_id = IrConfigParam.get_param('helpdesk_sale_order_ai.default_prompt_template_id', False)
if template_id:
try:
template_id_int = int(template_id) if isinstance(template_id, str) else template_id
res['helpdesk_ai_prompt_template_id'] = template_id_int
except (ValueError, TypeError):
_logger.error(f"Invalid template ID in system parameter: {template_id}")
return res
def set_values(self):
"""Set values from the settings form"""
super(ResConfigSettings, self).set_values()
# Save the template ID to the system parameter
IrConfigParam = self.env['ir.config_parameter'].sudo()
if self.helpdesk_ai_prompt_template_id:
IrConfigParam.set_param('helpdesk_sale_order_ai.default_prompt_template_id', str(self.helpdesk_ai_prompt_template_id.id))
else:
# If no template is selected, ensure there's a default one
self._set_default_values()
@api.model
def _get_openwebui_models(self):
"""Get available models from OpenWebUI API"""
try:
client = self.env['openwebui.client']
models = client.get_available_models()
return models
except Exception as e:
_logger.error(f"Error fetching OpenWebUI models: {e}")
# Return default model on error
default_model = 'anthropic.claude-3-7-sonnet-latest'
return [(default_model, default_model)]
@api.model
def _set_default_values(self):
"""Set default values for configuration parameters"""
# Ensure there's a default template
template_model = self.env['openwebui.prompt.template']
template_model._ensure_default_template()
default_template = template_model.get_default_template()
# Set the default template ID in config parameters if not set
IrConfigParam = self.env['ir.config_parameter'].sudo()
default_template_id = IrConfigParam.get_param('helpdesk_sale_order_ai.default_prompt_template_id')
if not default_template_id and default_template:
# Store as string to ensure compatibility with the OpenAI connector module
IrConfigParam.set_param('helpdesk_sale_order_ai.default_prompt_template_id', str(default_template.id))
@api.model
def get_prompt_template(self):
"""Get the prompt template content from the selected template or default"""
IrConfigParam = self.env['ir.config_parameter'].sudo()
template_id = IrConfigParam.get_param('helpdesk_sale_order_ai.default_prompt_template_id', False)
if template_id:
try:
# Make sure the template model exists first
self.env['openwebui.prompt.template']._ensure_default_template('helpdesk')
# The template_id is already an integer in the database now
template_id_int = int(template_id) if isinstance(template_id, str) else template_id
template = self.env['openwebui.prompt.template'].browse(template_id_int)
if template.exists():
return template.content
except (ValueError, TypeError) as e:
_logger.error(f"Error retrieving prompt template: {e}")
pass
# Fallback to default template
default_template = self.env['openwebui.prompt.template'].get_default_template('helpdesk')
return default_template.content if default_template else ""