81 lines
3.8 KiB
Python
81 lines
3.8 KiB
Python
from __future__ import annotations
|
|
|
|
from collections.abc import Callable
|
|
from typing import Annotated, Any
|
|
|
|
from pydantic import Field
|
|
|
|
SafeResult = Callable[[Callable[[], dict[str, Any]]], dict[str, Any]]
|
|
SafeRawResult = Callable[[bool, Callable[[], dict[str, Any]]], dict[str, Any]]
|
|
|
|
|
|
def register_project_tools(server: Any, service: Any, safe_result: SafeResult, safe_raw_result: SafeRawResult) -> None:
|
|
@server.tool()
|
|
def list_projects(
|
|
customer_id: Annotated[Any | None, Field(description="Optional customer ID.")] = None,
|
|
team: Annotated[str | None, Field(description="Optional CRM team name.")] = None,
|
|
stage: Annotated[str | None, Field(description="Optional project stage label or configured value.")] = None,
|
|
limit: Annotated[int, Field(description="Maximum projects to return.")] = 20,
|
|
offset: Annotated[int, Field(description="Zero-based result offset.")] = 0,
|
|
include_raw: Annotated[bool, Field(description="Include original NocoBase project rows.")] = False,
|
|
) -> dict[str, Any]:
|
|
"""List CRM projects linked to customers, teams, and project stages."""
|
|
return safe_raw_result(
|
|
include_raw,
|
|
lambda: service.list_projects(
|
|
customer_id=customer_id,
|
|
team=team,
|
|
stage=stage,
|
|
limit=limit,
|
|
offset=offset,
|
|
include_raw=include_raw,
|
|
),
|
|
)
|
|
|
|
@server.tool()
|
|
def get_project(
|
|
project_id: Annotated[Any, Field(description="NocoBase CRM project ID.")],
|
|
include_contacts: Annotated[bool, Field(description="Include related contacts.")] = True,
|
|
include_followups: Annotated[bool, Field(description="Include related follow-ups.")] = True,
|
|
include_updates: Annotated[bool, Field(description="Include project update records.")] = True,
|
|
) -> dict[str, Any]:
|
|
"""Get a CRM project with its existing NocoBase relations."""
|
|
return safe_result(
|
|
lambda: service.get_project(
|
|
project_id,
|
|
include_contacts=include_contacts,
|
|
include_followups=include_followups,
|
|
include_updates=include_updates,
|
|
)
|
|
)
|
|
|
|
@server.tool()
|
|
def get_project_timeline(
|
|
project_id: Annotated[Any, Field(description="NocoBase CRM project ID.")],
|
|
date_from: Annotated[str | None, Field(description="Optional lower event date bound.")] = None,
|
|
date_to: Annotated[str | None, Field(description="Optional upper event date bound.")] = None,
|
|
) -> dict[str, Any]:
|
|
"""Return a chronological CRM project timeline from follow-ups and project updates."""
|
|
return safe_result(lambda: service.get_project_timeline(project_id, date_from=date_from, date_to=date_to))
|
|
|
|
@server.tool()
|
|
def list_stale_customers(
|
|
team: Annotated[str | None, Field(description="Optional CRM team name.")] = None,
|
|
owner: Annotated[str | None, Field(description="Optional customer owner.")] = None,
|
|
inactive_days: Annotated[int, Field(description="Days without a valid follow-up.")] = 30,
|
|
as_of: Annotated[str | None, Field(description="Reference date in YYYY-MM-DD format.")] = None,
|
|
limit: Annotated[int, Field(description="Maximum customers to return.")] = 20,
|
|
offset: Annotated[int, Field(description="Zero-based result offset.")] = 0,
|
|
) -> dict[str, Any]:
|
|
"""List customers whose last valid follow-up is older than the configured threshold."""
|
|
return safe_result(
|
|
lambda: service.list_stale_customers(
|
|
team=team,
|
|
owner=owner,
|
|
inactive_days=inactive_days,
|
|
as_of=as_of,
|
|
limit=limit,
|
|
offset=offset,
|
|
)
|
|
)
|