122 lines
4.1 KiB
Python
122 lines
4.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright 2026 Nexa Systems Inc.
|
|
# License OPL-1 (Odoo Proprietary License v1.0)
|
|
|
|
import logging
|
|
from datetime import datetime, timedelta, date
|
|
from odoo import http, _
|
|
from odoo.http import request
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class FusionClockPortalAI(http.Controller):
|
|
|
|
def _get_employee(self):
|
|
return request.env['hr.employee'].sudo().search([
|
|
('user_id', '=', request.env.uid),
|
|
], limit=1)
|
|
|
|
@http.route('/fusion_clock_ai/employee_chat', type='json', auth='user')
|
|
def employee_chat(self, message, conversation_id=None):
|
|
ICP = request.env['ir.config_parameter'].sudo()
|
|
if ICP.get_param('fusion_clock_ai.enable_employee_chat', 'True') != 'True':
|
|
return {'error': 'AI Assistant is currently disabled.'}
|
|
|
|
employee = self._get_employee()
|
|
if not employee:
|
|
return {'error': 'No employee record found.'}
|
|
|
|
AI = request.env['fusion.clock.ai.service'].sudo()
|
|
|
|
context_data = AI._build_employee_context(
|
|
employee,
|
|
date.today() - timedelta(days=30),
|
|
date.today(),
|
|
)
|
|
|
|
Conversation = request.env['fusion.clock.ai.conversation'].sudo()
|
|
if conversation_id:
|
|
conv = Conversation.browse(int(conversation_id))
|
|
if not conv.exists() or conv.user_id.id != request.env.uid:
|
|
conv = Conversation.create({
|
|
'user_id': request.env.uid,
|
|
'conversation_type': 'employee_chat',
|
|
})
|
|
else:
|
|
conv = Conversation.create({
|
|
'user_id': request.env.uid,
|
|
'conversation_type': 'employee_chat',
|
|
})
|
|
|
|
Message = request.env['fusion.clock.ai.message'].sudo()
|
|
Message.create({
|
|
'conversation_id': conv.id,
|
|
'role': 'user',
|
|
'content': message,
|
|
})
|
|
|
|
system_prompt = AI._get_system_prompt('employee_chat')
|
|
messages = [
|
|
{'role': 'system', 'content': f"{system_prompt}\n\n--- YOUR ATTENDANCE DATA ---\n{context_data}"},
|
|
]
|
|
for msg in conv.message_ids:
|
|
messages.append({'role': msg.role, 'content': msg.content})
|
|
|
|
try:
|
|
response = AI.chat_completion(messages, feature='employee_chat')
|
|
except Exception as e:
|
|
return {'error': str(e)}
|
|
|
|
Message.create({
|
|
'conversation_id': conv.id,
|
|
'role': 'assistant',
|
|
'content': response,
|
|
})
|
|
|
|
return {
|
|
'response': response,
|
|
'conversation_id': conv.id,
|
|
}
|
|
|
|
@http.route('/fusion_clock_ai/polish_reason', type='json', auth='user')
|
|
def polish_reason(self, rough_text):
|
|
AI = request.env['fusion.clock.ai.service'].sudo()
|
|
system_prompt = AI._get_system_prompt('leave_reason_writer')
|
|
try:
|
|
response = AI.chat_completion(
|
|
[
|
|
{'role': 'system', 'content': system_prompt},
|
|
{'role': 'user', 'content': rough_text},
|
|
],
|
|
feature='leave_reason_writer',
|
|
)
|
|
except Exception as e:
|
|
return {'error': str(e)}
|
|
return {'polished': response}
|
|
|
|
@http.route('/fusion_clock_ai/my_coach_tip', type='json', auth='user')
|
|
def my_coach_tip(self):
|
|
employee = self._get_employee()
|
|
if not employee:
|
|
return {'error': 'No employee record found.'}
|
|
|
|
AI = request.env['fusion.clock.ai.service'].sudo()
|
|
context_data = AI._build_employee_context(
|
|
employee,
|
|
date.today() - timedelta(days=14),
|
|
date.today(),
|
|
)
|
|
system_prompt = AI._get_system_prompt('attendance_coach')
|
|
try:
|
|
response = AI.chat_completion(
|
|
[
|
|
{'role': 'system', 'content': system_prompt},
|
|
{'role': 'user', 'content': context_data},
|
|
],
|
|
feature='attendance_coach',
|
|
)
|
|
except Exception as e:
|
|
return {'error': str(e)}
|
|
return {'tip': response}
|