"""
Base utilities for MCP tools.
Provides common functionality shared across all tool modules.
"""
from __future__ import annotations
from typing import Any
from ..client import OdooClient, get_client
from ..constants import DEFAULT_LIMIT, DEFAULT_OFFSET, MAX_LIMIT
from ..formatters import MarkdownBuilder, format_many2one
def get_odoo_client() -> OdooClient:
"""
Get the shared Odoo client instance.
Returns:
OdooClient instance
"""
return get_client()
def normalize_pagination(
limit: int | None = None,
offset: int | None = None,
) -> tuple[int, int]:
"""
Normalize pagination parameters.
Args:
limit: Requested limit (None for default)
offset: Requested offset (None for default)
Returns:
Tuple of (normalized_limit, normalized_offset)
"""
normalized_limit = min(limit or DEFAULT_LIMIT, MAX_LIMIT)
normalized_offset = max(offset or DEFAULT_OFFSET, 0)
return normalized_limit, normalized_offset
def build_domain(
filters: dict[str, Any],
field_mapping: dict[str, str] | None = None,
) -> list[Any]:
"""
Build an Odoo domain from filter parameters.
Args:
filters: Dictionary of filter field -> value
field_mapping: Optional mapping of param names to Odoo field names
Returns:
Odoo domain list
"""
domain: list[Any] = []
mapping = field_mapping or {}
for param, value in filters.items():
if value is None:
continue
field = mapping.get(param, param)
if isinstance(value, bool):
domain.append((field, "=", value))
elif isinstance(value, str):
domain.append((field, "=", value))
elif isinstance(value, int):
domain.append((field, "=", value))
elif isinstance(value, (list, tuple)):
domain.append((field, "in", list(value)))
return domain
def extract_name(value: Any, default: str = "N/A") -> str:
"""
Extract display name from Odoo field value.
Handles Many2one fields (tuple), regular values, and False values.
Args:
value: Field value from Odoo
default: Default value if extraction fails
Returns:
Display name string
"""
name = format_many2one(value)
if name:
return name
if value and value is not False:
return str(value)
return default
def extract_id(value: Any) -> int | None:
"""
Extract ID from Odoo field value.
Args:
value: Field value (Many2one tuple or int)
Returns:
ID or None
"""
if isinstance(value, (list, tuple)) and len(value) >= 1:
return int(value[0])
if isinstance(value, int) and value > 0:
return value
return None
def format_state(state: str, labels: dict[str, str]) -> str:
"""
Format a state value using labels.
Args:
state: State value
labels: Dictionary of state -> label
Returns:
Formatted state label
"""
return labels.get(state, state.replace("_", " ").title())
def add_pagination_info(
builder: MarkdownBuilder,
count: int,
limit: int,
offset: int,
total: int | None = None,
) -> MarkdownBuilder:
"""
Add pagination info to a MarkdownBuilder.
Args:
builder: MarkdownBuilder instance
count: Number of items in current page
limit: Page size limit
offset: Current offset
total: Total count (if known)
Returns:
The builder for chaining
"""
return builder.add_pagination(count, limit, offset, total)