import logging from odoo import fields _logger = logging.getLogger(__name__) def get_stock_valuation(env, params): accounts = env['account.account'].search([ ('code', '=like', '1069%'), ('company_id', '=', env.company.id), ]) result = [] for acct in accounts: balance = sum(env['account.move.line'].search([ ('account_id', '=', acct.id), ('parent_state', '=', 'posted'), ]).mapped('balance')) result.append({'code': acct.code, 'name': acct.name, 'balance': balance}) return {'accounts': result, 'total': sum(r['balance'] for r in result)} def get_price_differences(env, params): accounts = env['account.account'].search([ ('code', '=like', '5010%'), ('company_id', '=', env.company.id), ]) domain = [ ('account_id', 'in', accounts.ids), ('parent_state', '=', 'posted'), ('company_id', '=', env.company.id), ] if params.get('date_from'): domain.append(('date', '>=', params['date_from'])) if params.get('date_to'): domain.append(('date', '<=', params['date_to'])) lines = env['account.move.line'].search(domain, order='date desc', limit=50) return { 'total': sum(l.balance for l in lines), 'entries': [{ 'id': l.id, 'date': str(l.date), 'move': l.move_id.name, 'amount': l.balance, 'partner': l.partner_id.name if l.partner_id else '', } for l in lines], } def get_cogs_ratio_by_category(env, params): date_from = params.get('date_from') date_to = params.get('date_to') base_domain = [ ('parent_state', '=', 'posted'), ('company_id', '=', env.company.id), ] if date_from: base_domain.append(('date', '>=', date_from)) if date_to: base_domain.append(('date', '<=', date_to)) revenue_lines = env['account.move.line'].search( base_domain + [('account_id.account_type', '=', 'income')] ) cogs_lines = env['account.move.line'].search( base_domain + [('account_id.account_type', '=', 'expense_direct_cost')] ) revenue = abs(sum(l.balance for l in revenue_lines)) cogs = abs(sum(l.balance for l in cogs_lines)) ratio = (cogs / revenue * 100) if revenue else 0 return {'revenue': revenue, 'cogs': cogs, 'ratio_pct': round(ratio, 2)} def find_unusual_adjustments(env, params): threshold = float(params.get('threshold', 1000)) domain = [ ('parent_state', '=', 'posted'), ('company_id', '=', env.company.id), ('account_id.account_type', '=', 'expense_direct_cost'), ] lines = env['account.move.line'].search(domain) unusual = lines.filtered(lambda l: abs(l.balance) > threshold) return { 'count': len(unusual), 'adjustments': [{ 'id': l.id, 'date': str(l.date), 'move': l.move_id.name, 'amount': l.balance, 'name': l.name or '', } for l in unusual[:20]], } def get_inventory_turnover(env, params): from .reporting import get_profit_loss pl = get_profit_loss(env, params) stock = get_stock_valuation(env, params) avg_inventory = stock.get('total', 0) cogs = 0 for line in pl.get('lines', []): if 'cost' in line.get('name', '').lower(): cols = line.get('columns', []) if cols: try: cogs = float(cols[0]) except (ValueError, TypeError): pass turnover = (cogs / avg_inventory) if avg_inventory else 0 return {'cogs': cogs, 'avg_inventory': avg_inventory, 'turnover': round(turnover, 2)} TOOLS = { 'get_stock_valuation': get_stock_valuation, 'get_price_differences': get_price_differences, 'get_cogs_ratio_by_category': get_cogs_ratio_by_category, 'find_unusual_adjustments': find_unusual_adjustments, 'get_inventory_turnover': get_inventory_turnover, }