Files
clientflow_backend/app/odoo_client.py
2026-06-09 22:55:58 +01:00

127 lines
3.7 KiB
Python

from __future__ import annotations
import ssl
import xmlrpc.client
from dataclasses import dataclass
from typing import Any, Dict, List, Optional
from app.config import settings
class OdooIntegrationError(RuntimeError):
pass
@dataclass
class OdooConfig:
base_url: str
db: str
username: str
api_key: str
def get_odoo_config() -> OdooConfig:
base_url = (settings.odoo_base_url or "").rstrip("/")
db = settings.odoo_db or ""
username = settings.odoo_username or ""
api_key = settings.odoo_api_key or ""
if not base_url:
raise OdooIntegrationError("ODOO_BASE_URL não está configurado.")
if not db:
raise OdooIntegrationError("ODOO_DB não está configurado.")
if not username:
raise OdooIntegrationError("ODOO_USERNAME não está configurado.")
if not api_key:
raise OdooIntegrationError("ODOO_API_KEY não está configurado.")
return OdooConfig(base_url=base_url, db=db, username=username, api_key=api_key)
class OdooClient:
def __init__(self, config: Optional[OdooConfig] = None):
self.config = config or get_odoo_config()
self._uid: Optional[int] = None
context = ssl._create_unverified_context()
self.common = xmlrpc.client.ServerProxy(
f"{self.config.base_url}/xmlrpc/2/common",
allow_none=True,
context=context,
)
self.models = xmlrpc.client.ServerProxy(
f"{self.config.base_url}/xmlrpc/2/object",
allow_none=True,
context=context,
)
def version(self) -> Dict[str, Any]:
try:
return dict(self.common.version())
except Exception as exc:
raise OdooIntegrationError(f"Falha ao consultar versão Odoo: {exc}") from exc
def authenticate(self) -> int:
if self._uid:
return self._uid
try:
uid = self.common.authenticate(
self.config.db,
self.config.username,
self.config.api_key,
{},
)
except Exception as exc:
raise OdooIntegrationError(f"Falha de autenticação Odoo: {exc}") from exc
if not uid:
raise OdooIntegrationError("Autenticação Odoo falhou. Verifica ODOO_USERNAME e ODOO_API_KEY/password.")
self._uid = int(uid)
return self._uid
def execute_kw(
self,
model: str,
method: str,
args: Optional[List[Any]] = None,
kwargs: Optional[Dict[str, Any]] = None,
) -> Any:
uid = self.authenticate()
try:
return self.models.execute_kw(
self.config.db,
uid,
self.config.api_key,
model,
method,
args or [],
kwargs or {},
)
except Exception as exc:
raise OdooIntegrationError(f"Odoo {model}.{method} falhou: {exc}") from exc
def search_read(
self,
model: str,
domain: Optional[List[Any]] = None,
fields: Optional[List[str]] = None,
*,
limit: int = 500,
offset: int = 0,
order: str = "id asc",
context: Optional[Dict[str, Any]] = None,
) -> List[Dict[str, Any]]:
kwargs: Dict[str, Any] = {
"fields": fields or [],
"limit": int(limit),
"offset": int(offset),
"order": order,
}
if context is not None:
kwargs["context"] = context
return list(self.execute_kw(model, "search_read", [domain or []], kwargs) or [])
def count(self, model: str, domain: Optional[List[Any]] = None) -> int:
return int(self.execute_kw(model, "search_count", [domain or []]) or 0)