162 lines
7.6 KiB
Python
162 lines
7.6 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_record_tools(server: Any, service: Any, safe_result: SafeResult, safe_raw_result: SafeRawResult) -> None:
|
|
@server.tool()
|
|
def list_customers(
|
|
query: Annotated[str | None, Field(description="Optional customer keyword search.")] = None,
|
|
status: Annotated[str | None, Field(description="Optional exact customer status.")] = None,
|
|
owner: Annotated[
|
|
str | None, Field(description="Optional customer owner name, username, email, or English name.")
|
|
] = None,
|
|
team: Annotated[str | None, Field(description="Optional CRM team name.")] = None,
|
|
source: Annotated[str | None, Field(description="Optional exact customer source.")] = None,
|
|
limit: Annotated[int, Field(description="Maximum rows to return. Defaults to 20.")] = 20,
|
|
offset: Annotated[int, Field(description="Zero-based result offset. Defaults to 0.")] = 0,
|
|
include_raw: Annotated[
|
|
bool, Field(description="When true, include the original NocoBase row under raw. Defaults to false.")
|
|
] = False,
|
|
) -> dict[str, Any]:
|
|
"""List CRM customers with compact rows and pagination metadata.
|
|
|
|
Rows are {id, name, english_name, territorial_name, status, source,
|
|
owners: [{id, name}], managers, createdAt, updatedAt}. Empty values are
|
|
omitted. A name shown as "#123" means that customer has no name recorded.
|
|
"""
|
|
return safe_raw_result(
|
|
include_raw,
|
|
lambda: service.list_customers(
|
|
query=query,
|
|
status=status,
|
|
owner=owner,
|
|
team=team,
|
|
source=source,
|
|
limit=limit,
|
|
offset=offset,
|
|
include_raw=include_raw,
|
|
),
|
|
)
|
|
|
|
@server.tool()
|
|
def get_customer(
|
|
customer_id: Annotated[Any, Field(description="Customer primary key value.")],
|
|
include_contacts: Annotated[bool, Field(description="Include related contacts.")] = True,
|
|
include_recent_followups: Annotated[bool, Field(description="Include recent related follow-ups.")] = True,
|
|
followup_limit: Annotated[int, Field(description="Maximum related follow-ups to return.")] = 10,
|
|
include_raw: Annotated[
|
|
bool,
|
|
Field(description="When true, include original NocoBase rows under raw. Defaults to false."),
|
|
] = False,
|
|
) -> dict[str, Any]:
|
|
"""Get one customer with its contacts and recent follow-ups.
|
|
|
|
Returns {customer, contacts, recent_followups, timezone}. The customer is
|
|
{id, name, english_name, territorial_name, status, source, owners, managers,
|
|
address, intro, tags, ...} using readable keys, never NocoBase field codes.
|
|
Contacts are {id, name, title} without phone or email -- call list_contacts
|
|
for those. Follow-ups use the same row shape as list_followups. Empty values
|
|
are omitted, so a missing key means empty rather than unknown.
|
|
"""
|
|
return safe_raw_result(
|
|
include_raw,
|
|
lambda: service.get_customer(
|
|
customer_id,
|
|
include_contacts=include_contacts,
|
|
include_recent_followups=include_recent_followups,
|
|
followup_limit=followup_limit,
|
|
include_raw=include_raw,
|
|
),
|
|
)
|
|
|
|
@server.tool()
|
|
def list_contacts(
|
|
customer_id: Annotated[
|
|
Any | None, Field(description="Optional customer primary key for relation filtering.")
|
|
] = None,
|
|
query: Annotated[str | None, Field(description="Optional contact keyword search.")] = None,
|
|
limit: Annotated[int, Field(description="Maximum rows to return. Defaults to 20.")] = 20,
|
|
offset: Annotated[int, Field(description="Zero-based result offset. Defaults to 0.")] = 0,
|
|
include_details: Annotated[
|
|
bool,
|
|
Field(description="Include contact phone and email. Defaults to true."),
|
|
] = True,
|
|
include_raw: Annotated[
|
|
bool, Field(description="When true, include the original NocoBase row under raw. Defaults to false.")
|
|
] = False,
|
|
) -> dict[str, Any]:
|
|
"""List CRM contacts as compact rows, optionally filtered by customer.
|
|
|
|
Rows are {id, name, title, phone, email, customers: [{id, name}],
|
|
createdAt, updatedAt}. Set include_details=false to omit phone and email.
|
|
Empty values are omitted.
|
|
"""
|
|
return safe_raw_result(
|
|
include_raw,
|
|
lambda: service.list_contacts(
|
|
customer_id=customer_id,
|
|
query=query,
|
|
limit=limit,
|
|
offset=offset,
|
|
include_details=include_details,
|
|
include_raw=include_raw,
|
|
),
|
|
)
|
|
|
|
@server.tool()
|
|
def list_followups(
|
|
customer_id: Annotated[
|
|
Any | None, Field(description="Optional customer primary key for relation filtering.")
|
|
] = None,
|
|
contact_id: Annotated[
|
|
Any | None, Field(description="Optional contact primary key for relation filtering.")
|
|
] = None,
|
|
owner: Annotated[
|
|
str | None, Field(description="Optional follow-up participant name, username, email, or English name.")
|
|
] = None,
|
|
team: Annotated[str | None, Field(description="Optional CRM team name.")] = None,
|
|
project_id: Annotated[Any | None, Field(description="Optional CRM project ID.")] = None,
|
|
followup_type: Annotated[str | None, Field(description="Optional exact follow-up type value.")] = None,
|
|
record_status: Annotated[str | None, Field(description="Optional exact follow-up record status value.")] = None,
|
|
date_from: Annotated[str | None, Field(description="Optional lower follow-up date bound.")] = None,
|
|
date_to: Annotated[str | None, Field(description="Optional upper follow-up date bound.")] = None,
|
|
limit: Annotated[int, Field(description="Maximum rows to return. Defaults to 20.")] = 20,
|
|
offset: Annotated[int, Field(description="Zero-based result offset. Defaults to 0.")] = 0,
|
|
include_raw: Annotated[
|
|
bool, Field(description="When true, include the original NocoBase row under raw. Defaults to false.")
|
|
] = False,
|
|
) -> dict[str, Any]:
|
|
"""List customer follow-up records as compact rows with pagination metadata.
|
|
|
|
Rows are {id, followedAt, customers: [{id, name}], contacts, participants,
|
|
projects, type, status, location, content}. Content is the full follow-up
|
|
text, never truncated. type and status are the display labels; use
|
|
crm_filter_options for the codes the followup_type and record_status
|
|
filters expect. creator appears only when the submitter is not also a
|
|
participant. Empty values are omitted.
|
|
"""
|
|
return safe_raw_result(
|
|
include_raw,
|
|
lambda: service.list_followups(
|
|
customer_id=customer_id,
|
|
contact_id=contact_id,
|
|
owner=owner,
|
|
team=team,
|
|
project_id=project_id,
|
|
followup_type=followup_type,
|
|
record_status=record_status,
|
|
date_from=date_from,
|
|
date_to=date_to,
|
|
limit=limit,
|
|
offset=offset,
|
|
include_raw=include_raw,
|
|
),
|
|
)
|