| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- class SaveFuelRateTool:
- name = 'save_fuel_rate'
- route_path = '/mcp/tools/saveFuelRate'
- backend = 'base'
- def __init__(self, api_client=None):
- self.api_client = api_client
- def metadata(self):
- return {
- 'name': self.name,
- 'description': (
- '使用场景:按计费条件新增燃油系数,或编辑一条草稿燃油系数。'
- '新增时不要传燃油代码。编辑时必须传query_fuel_rate_list返回的燃油代码,并且只能提交一条费率。'
- '必须带燃油类型、开始生效时间,以及至少一条费率和计费条件。'
- '结束生效时间不传时按9999-12-31长期有效。'
- '燃油类型为1或销售燃油、2或成本燃油。编辑时不能修改燃油类型。'
- '只能编辑草稿,且只能编辑计费条件配置。'
- '计费条件和条件值都可以填代码或名称,必须完整匹配,不能按包含搜索。'
- '销售燃油可选物流产品、物流产品分类、仓库、地址库。'
- '成本燃油可选物流渠道、物流渠道分类、仓库、地址库。'
- '地址库可以填PY编号或地址库名称。'
- '同一条件组第一条不要填关系;后面的关系不传时按and。同一组不能同时使用and和or。'
- '新增和编辑后都是草稿,不会立即参与计费。生效请使用enable_fuel_rate。'
- '禁止使用:失效、删除、复制、手填不存在的燃油代码。'
- '参数只用于工具内部调用;最终回答只能展示中文业务名称和燃油代码。'
- ),
- 'input_schema': {
- 'type': 'object',
- 'properties': {
- 'price_type': {
- 'type': 'string',
- 'minLength': 1,
- 'maxLength': 20,
- 'description': '燃油类型。1或销售燃油,2或成本燃油。',
- },
- 'start_date': {
- 'type': 'string',
- 'minLength': 8,
- 'maxLength': 30,
- 'description': '开始生效时间,格式YYYY-MM-DD。',
- },
- 'end_date': {
- 'type': 'string',
- 'minLength': 8,
- 'maxLength': 30,
- 'description': '结束生效时间,格式YYYY-MM-DD。不传表示9999-12-31。',
- },
- 'fuel_no': {
- 'type': 'string',
- 'minLength': 1,
- 'maxLength': 20,
- 'description': '要编辑的燃油代码,格式为RY加数字。新增时不要传。',
- },
- 'items': {
- 'type': 'array',
- 'minItems': 1,
- 'maxItems': 20,
- 'items': {
- 'type': 'object',
- 'properties': {
- 'fuel_ratio': {
- 'type': 'string',
- 'minLength': 1,
- 'maxLength': 10,
- 'description': '燃油费率,0到1,最多4位小数。',
- },
- 'conditions': {
- 'type': 'array',
- 'minItems': 1,
- 'maxItems': 30,
- 'items': {
- 'type': 'object',
- 'properties': {
- 'condition': {
- 'type': 'string',
- 'minLength': 1,
- 'maxLength': 50,
- 'description': '计费条件代码或名称,必须完整匹配。',
- },
- 'group': {
- 'type': 'string',
- 'minLength': 1,
- 'maxLength': 20,
- 'description': '条件组编号,同组条件写同一个组号。',
- },
- 'condition_value': {
- 'type': 'string',
- 'minLength': 1,
- 'maxLength': 100,
- 'description': '条件值代码或名称,必须完整匹配。多选用英文逗号分隔。',
- },
- 'condition_relation': {
- 'type': 'string',
- 'enum': ['and', 'or'],
- 'description': '与同组上一条的关系。同组第一条不要传。',
- },
- },
- 'required': ['condition', 'group', 'condition_value'],
- 'additionalProperties': False,
- },
- },
- },
- 'required': ['fuel_ratio', 'conditions'],
- 'additionalProperties': False,
- },
- },
- },
- 'required': ['price_type', 'start_date', 'items'],
- 'additionalProperties': False,
- },
- }
- def call(
- self,
- price_type,
- start_date,
- items,
- end_date=None,
- fuel_no=None,
- request_id='rq_save_fuel_rate',
- ):
- if self.api_client is None:
- raise RuntimeError('api client is required for save_fuel_rate')
- built_items = _items(items)
- payload = {
- 'price_type': _choice(price_type, ('1', '2', '销售燃油', '成本燃油'), 'price_type'),
- 'start_date': _date(start_date, 'start_date'),
- 'items': built_items,
- }
- if end_date is not None:
- payload['end_date'] = _date(end_date, 'end_date')
- if fuel_no is not None:
- if not isinstance(fuel_no, str) or not fuel_no.strip() or len(fuel_no.strip()) > 20:
- raise ValueError('fuel_no is invalid')
- if len(built_items) != 1:
- raise ValueError('items is invalid')
- payload['fuel_no'] = fuel_no.strip()
- return self.api_client.call_tool(self.name, self.route_path, payload, request_id)
- def _choice(value, choices, key):
- if isinstance(value, bool):
- raise ValueError(key + ' is invalid')
- if isinstance(value, int):
- value = str(value)
- if not isinstance(value, str) or value.strip() not in choices:
- raise ValueError(key + ' is invalid')
- return value.strip()
- def _date(value, key):
- if not isinstance(value, str) or not value.strip() or len(value.strip()) > 30:
- raise ValueError(key + ' is invalid')
- return value.strip()
- def _items(items):
- if not isinstance(items, list) or not items or len(items) > 20:
- raise ValueError('items is invalid')
- rows = []
- for item in items:
- if not isinstance(item, dict) or set(item) - {'fuel_ratio', 'conditions'}:
- raise ValueError('items is invalid')
- ratio = item.get('fuel_ratio')
- if isinstance(ratio, bool) or isinstance(ratio, int) or isinstance(ratio, float):
- ratio = '{0:.4f}'.format(ratio)
- if not isinstance(ratio, str) or not ratio.strip() or len(ratio.strip()) > 10:
- raise ValueError('fuel_ratio is invalid')
- rows.append({
- 'fuel_ratio': ratio.strip(),
- 'conditions': _conditions(item.get('conditions')),
- })
- return rows
- def _conditions(conditions):
- if not isinstance(conditions, list) or not conditions or len(conditions) > 30:
- raise ValueError('conditions is invalid')
- rows = []
- allowed = {'condition', 'group', 'condition_value', 'condition_relation'}
- for condition in conditions:
- if not isinstance(condition, dict) or set(condition) - allowed:
- raise ValueError('conditions is invalid')
- row = {
- 'condition': _text(condition.get('condition'), 50, 'condition'),
- 'group': _text(condition.get('group'), 20, 'group'),
- 'condition_value': _text(condition.get('condition_value'), 100, 'condition_value'),
- }
- relation = condition.get('condition_relation')
- if relation is not None:
- if relation not in ('and', 'or'):
- raise ValueError('condition_relation is invalid')
- row['condition_relation'] = relation
- rows.append(row)
- return rows
- def _text(value, max_length, key):
- if not isinstance(value, str) or not value.strip() or len(value.strip()) > max_length:
- raise ValueError(key + ' is invalid')
- return value.strip()
|