from __future__ import annotations import logging from ..tools.odoo_client import OdooClient logger = logging.getLogger(__name__) class ProjectTools: def __init__(self, odoo: OdooClient): self._o = odoo async def get_projects(self, active: bool = True, limit: int = 50) -> list: domain = [('active', '=', active)] fields = ['name', 'partner_id', 'user_id', 'date_start', 'date', 'task_count', 'description', 'last_update_status'] return await self._o.search_read('project.project', domain, fields, limit=limit) async def get_tasks(self, project_id: int = None, stage_id: int = None, user_id: int = None, limit: int = 100) -> list: domain = [('active', '=', True)] if project_id: domain.append(('project_id', '=', project_id)) if stage_id: domain.append(('stage_id', '=', stage_id)) if user_id: domain.append(('user_ids', 'in', [user_id])) fields = ['name', 'project_id', 'stage_id', 'user_ids', 'date_deadline', 'priority', 'kanban_state', 'description', 'tag_ids'] return await self._o.search_read('project.task', domain, fields, limit=limit) async def get_project_summary(self, project_id: int) -> dict: tasks = await self._o.search_read( 'project.task', [('project_id', '=', project_id), ('active', '=', True)], ['stage_id', 'kanban_state', 'date_deadline', 'user_ids'], limit=500, ) total = len(tasks) blocked = [t for t in tasks if t.get('kanban_state') == 'blocked'] overdue = [t for t in tasks if t.get('date_deadline') and t['date_deadline'] < str(__import__('datetime').date.today())] return { 'project_id': project_id, 'total_tasks': total, 'blocked_tasks': len(blocked), 'overdue_tasks': len(overdue), } async def update_task_stage(self, task_id: int, stage_id: int) -> bool: result = await self._o.write('project.task', [task_id], {'stage_id': stage_id}) return result.success async def assign_task(self, task_id: int, user_id: int) -> bool: result = await self._o.write('project.task', [task_id], {'user_ids': [(4, user_id)]}) return result.success async def create_task(self, project_id: int, name: str, description: str = '', user_id: int = None, date_deadline: str = None) -> int: vals = {'project_id': project_id, 'name': name} if description: vals['description'] = description if user_id: vals['user_ids'] = [(4, user_id)] if date_deadline: vals['date_deadline'] = date_deadline record_id = await self._o.call('project.task', 'create', [vals]) logger.info('Created task %s in project %s', record_id, project_id) return record_id async def log_timesheet(self, task_id: int, employee_id: int, hours: float, description: str = '', date: str = None) -> int: import datetime vals = { 'task_id': task_id, 'employee_id': employee_id, 'unit_amount': hours, 'name': description or 'AI-logged timesheet', 'date': date or str(datetime.date.today()), } record_id = await self._o.call('account.analytic.line', 'create', [vals]) return record_id async def post_chatter_note(self, model: str, record_id: int, note: str) -> bool: await self._o.call(model, 'message_post', [[record_id]], {'body': note, 'message_type': 'comment'}) return True