from __future__ import annotations import logging from ..tools.odoo_client import OdooClient logger = logging.getLogger(__name__) class SalesTools: def __init__(self, odoo: OdooClient): self._o = odoo async def get_sales_orders(self, state: str = 'sale', partner_id: int = None, date_from: str = None, date_to: str = None, limit: int = 50) -> list: domain = [('state', '=', state)] if partner_id: domain.append(('partner_id', '=', partner_id)) if date_from: domain.append(('date_order', '>=', date_from)) if date_to: domain.append(('date_order', '<=', date_to)) fields = ['name', 'partner_id', 'state', 'date_order', 'amount_total', 'amount_untaxed', 'user_id', 'invoice_status'] return await self._o.search_read('sale.order', domain, fields, limit=limit) async def get_quotations(self, partner_id: int = None, limit: int = 50) -> list: domain = [('state', 'in', ['draft', 'sent'])] if partner_id: domain.append(('partner_id', '=', partner_id)) fields = ['name', 'partner_id', 'state', 'date_order', 'validity_date', 'amount_total', 'user_id'] return await self._o.search_read('sale.order', domain, fields, limit=limit) async def get_sales_summary(self, date_from: str = None, date_to: str = None) -> dict: domain = [('state', '=', 'sale')] if date_from: domain.append(('date_order', '>=', date_from)) if date_to: domain.append(('date_order', '<=', date_to)) orders = await self._o.search_read('sale.order', domain, ['amount_total', 'user_id'], limit=1000) total = sum(o.get('amount_total', 0) for o in orders) by_rep: dict = {} for o in orders: uid = o['user_id'][0] if isinstance(o['user_id'], list) else 0 uname = o['user_id'][1] if isinstance(o['user_id'], list) else 'Unknown' by_rep.setdefault(uid, {'name': uname, 'count': 0, 'total': 0.0}) by_rep[uid]['count'] += 1 by_rep[uid]['total'] += o.get('amount_total', 0) return { 'order_count': len(orders), 'total_revenue': total, 'by_sales_rep': sorted(by_rep.values(), key=lambda x: x['total'], reverse=True)[:10], } async def get_customer_orders(self, partner_id: int, limit: int = 20) -> list: return await self._o.search_read( 'sale.order', [('partner_id', '=', partner_id)], ['name', 'state', 'date_order', 'amount_total', 'invoice_status'], limit=limit, ) async def confirm_quotation(self, order_id: int) -> bool: try: await self._o.call('sale.order', 'action_confirm', [[order_id]]) logger.info('Confirmed quotation %s', order_id) return True except Exception as exc: logger.warning('confirm_quotation failed %s: %s', order_id, exc) return False async def update_order_note(self, order_id: int, note: str) -> bool: result = await self._o.write('sale.order', [order_id], {'note': note}) return result.success async def flag_for_review(self, model: str, record_id: int, reason: str, severity: str = 'medium') -> bool: msg = f'[AI FLAG - {severity.upper()}] {reason}' await self._o.call(model, 'message_post', [[record_id]], {'body': msg, 'message_type': 'comment'}) return True 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