| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105 |
- from datetime import date
- class QueryCustomerPaymentRecordsTool:
- name = 'query_customer_payment_records'
- route_path = '/mcp/tools/queryCustomerPaymentRecords'
- def __init__(self, api_client=None):
- self.api_client = api_client
- def metadata(self):
- return {
- 'name': self.name,
- 'description': (
- '分页查询单个客户的逐笔收款记录、已核销金额和未核销金额。必须先调用'
- 'list_customer_filter_options并使用客户名称筛选取得customer_id;不得根据名称猜测'
- 'customer_id,不得模糊查询或改用其他工具试查。收款日期可按闭区间筛选,'
- '起止日期同时提供时闭区间最多包含366个日历日。公司、员工、菜单权限和客户数据范围由'
- '当前设备会话确定,调用方不得覆盖。'
- ),
- 'input_schema': {
- 'type': 'object',
- 'properties': {
- 'customer_id': {'type': 'integer', 'minimum': 1},
- 'receive_date_start': {
- 'type': 'string', 'format': 'date',
- 'pattern': '^\\d{4}-\\d{2}-\\d{2}$',
- },
- 'receive_date_end': {
- 'type': 'string', 'format': 'date',
- 'pattern': '^\\d{4}-\\d{2}-\\d{2}$',
- },
- 'page': {
- 'type': 'integer', 'minimum': 1, 'maximum': 100,
- 'default': 1,
- },
- 'limit': {
- 'type': 'integer', 'minimum': 1, 'maximum': 100,
- 'default': 20,
- },
- },
- 'required': ['customer_id'],
- 'additionalProperties': False,
- },
- }
- def call(
- self,
- customer_id,
- receive_date_start=None,
- receive_date_end=None,
- page=1,
- limit=20,
- request_id='rq_query_customer_payment_records',
- ):
- if self.api_client is None:
- raise RuntimeError(
- 'api client is required for query_customer_payment_records'
- )
- start = self._optional_date(receive_date_start, 'receive_date_start')
- end = self._optional_date(receive_date_end, 'receive_date_end')
- if start and end:
- span = (date.fromisoformat(end) - date.fromisoformat(start)).days
- if span < 0 or span > 365:
- raise ValueError('receive date range is invalid')
- payload = {
- 'customer_id': self._positive_integer(customer_id, 'customer_id'),
- 'page': self._bounded_integer(page, 'page'),
- 'limit': self._bounded_integer(limit, 'limit'),
- }
- if start:
- payload['receive_date_start'] = start
- if end:
- payload['receive_date_end'] = end
- return self.api_client.call_tool(
- self.name, self.route_path, payload, request_id
- )
- @staticmethod
- def _positive_integer(value, field):
- if isinstance(value, bool) or not isinstance(value, int) or value < 1:
- raise ValueError('{0} is invalid'.format(field))
- return value
- @classmethod
- def _bounded_integer(cls, value, field):
- value = cls._positive_integer(value, field)
- if value > 100:
- raise ValueError('{0} is invalid'.format(field))
- return value
- @staticmethod
- def _optional_date(value, field):
- if value is None or value == '':
- return ''
- if not isinstance(value, str):
- raise ValueError('{0} is invalid'.format(field))
- try:
- parsed = date.fromisoformat(value)
- except ValueError:
- raise ValueError('{0} is invalid'.format(field))
- if parsed.isoformat() != value:
- raise ValueError('{0} is invalid'.format(field))
- return value
|