聚焦场景(空串/纯空白 → None) 归化处理
This commit is contained in:
@@ -9,6 +9,19 @@ import json
|
||||
from mcp.server import MCPServer
|
||||
from db import get_pool
|
||||
|
||||
|
||||
def _s(value):
|
||||
"""查询语句处的 str 归一化:None / 空串 / 纯空白 → 统一为 None,其他原值返回。
|
||||
|
||||
只处理 str 类型,不碰 int/float/list/bool。
|
||||
用法:在每个工具函数开头对所有 str 参数执行 `x = _s(x)`,
|
||||
确保后续 `if x:` / `if x is not None:` / LIKE 拼接 行为一致。
|
||||
"""
|
||||
if isinstance(value, str):
|
||||
return value if value.strip() else None
|
||||
return value
|
||||
|
||||
|
||||
app = MCPServer(
|
||||
name="mcp-for-erp-auto",
|
||||
description="汽车零部件智能报价 ERP 数据服务",
|
||||
@@ -28,6 +41,10 @@ async def query_material_master(
|
||||
die_casting_ton: int = None
|
||||
) -> str:
|
||||
"""查询 ERP 物料主数据。支持按物料编码精确查询,或按零件类别、材质、吨位等参数组合查询。返回物料列表,包含体积、重量、吨位等关键参数。"""
|
||||
# 查询语句处 str 归一化:空串/纯空白同 None
|
||||
material_code = _s(material_code)
|
||||
part_category = _s(part_category)
|
||||
material_grade = _s(material_grade)
|
||||
pool = await get_pool()
|
||||
query = "SELECT * FROM material_master WHERE 1=1"
|
||||
params = []
|
||||
@@ -58,6 +75,11 @@ async def query_material_master(
|
||||
@app.tool()
|
||||
async def match_material_grade(customer_grade: str, standard: str = None) -> str:
|
||||
"""将客户指定材质牌号自动对照为企业内部等效牌号。支持 GB/ASTM/JIS/EN/ISO 标准体系,返回等效牌号、密度、铝锭参考价。"""
|
||||
# 查询语句处 str 归一化:空串/纯空白同 None
|
||||
customer_grade = _s(customer_grade)
|
||||
standard = _s(standard)
|
||||
if customer_grade is None:
|
||||
return json.dumps({"matched": False, "message": "需提供 customer_grade(材质牌号)"}, ensure_ascii=False, indent=2)
|
||||
pool = await get_pool()
|
||||
|
||||
query = """
|
||||
@@ -97,6 +119,8 @@ async def match_material_grade(customer_grade: str, standard: str = None) -> str
|
||||
@app.tool()
|
||||
async def get_die_casting_params(material_code: str, volume_cc: float = None) -> str:
|
||||
"""根据物料编码获取压铸参数。返回压铸机吨位、模次节拍、铝水重量、压铸成本。铝水重量 = 体积 × 密度。"""
|
||||
# 查询语句处 str 归一化:空串/纯空白同 None
|
||||
material_code = _s(material_code)
|
||||
pool = await get_pool()
|
||||
|
||||
material = await pool.fetchrow("SELECT * FROM material_master WHERE material_code = $1", material_code)
|
||||
@@ -136,6 +160,8 @@ async def get_machining_estimate(
|
||||
mill_faces: int = 0
|
||||
) -> str:
|
||||
"""根据孔清单估算机加工工时。钻孔、攻丝、铰孔、铣面均有固化节拍,逐项累加得到总工时和成本。"""
|
||||
# 查询语句处 str 归一化:空串/纯空白同 None
|
||||
material_code = _s(material_code)
|
||||
pool = await get_pool()
|
||||
drill_holes = drill_holes or []
|
||||
tap_holes = tap_holes or []
|
||||
@@ -146,7 +172,7 @@ async def get_machining_estimate(
|
||||
details = []
|
||||
|
||||
for hole in drill_holes:
|
||||
spec = hole.get("spec", "Φ8")
|
||||
spec = _s(hole.get("spec", "Φ8")) or "Φ8"
|
||||
count = hole.get("count", 1)
|
||||
row = await pool.fetchrow("SELECT * FROM machining_cycle WHERE operation_type='drill' AND spec=$1", spec)
|
||||
if row:
|
||||
@@ -157,7 +183,7 @@ async def get_machining_estimate(
|
||||
details.append({"operation": "drill", "spec": spec, "count": count, "total_time_sec": time_sec})
|
||||
|
||||
for hole in tap_holes:
|
||||
spec = hole.get("spec", "M8×1.25")
|
||||
spec = _s(hole.get("spec", "M8×1.25")) or "M8×1.25"
|
||||
count = hole.get("count", 1)
|
||||
row = await pool.fetchrow("SELECT * FROM machining_cycle WHERE operation_type='tap' AND spec=$1", spec)
|
||||
if row:
|
||||
@@ -168,7 +194,7 @@ async def get_machining_estimate(
|
||||
details.append({"operation": "tap", "spec": spec, "count": count, "total_time_sec": time_sec})
|
||||
|
||||
for hole in ream_holes:
|
||||
spec = hole.get("spec", "Φ8H7")
|
||||
spec = _s(hole.get("spec", "Φ8H7")) or "Φ8H7"
|
||||
count = hole.get("count", 1)
|
||||
row = await pool.fetchrow("SELECT * FROM machining_cycle WHERE operation_type='ream' AND spec=$1", spec)
|
||||
if row:
|
||||
@@ -209,6 +235,8 @@ async def calculate_part_cost(
|
||||
profit_rate: float = 0.15
|
||||
) -> str:
|
||||
"""汇总核价:材料成本(铝水重量×单价)+ 压铸成本 + 机加工成本 + 后处理成本 + 管理费 + 利润。返回完整成本明细和最终报价。"""
|
||||
# 查询语句处 str 归一化:空串/纯空白同 None
|
||||
material_code = _s(material_code)
|
||||
pool = await get_pool()
|
||||
drill_holes = drill_holes or []
|
||||
tap_holes = tap_holes or []
|
||||
@@ -263,17 +291,20 @@ async def calculate_part_cost(
|
||||
total_machining_time_sec = 0
|
||||
|
||||
for hole in drill_holes:
|
||||
row = await pool.fetchrow("SELECT cycle_time_sec FROM machining_cycle WHERE operation_type='drill' AND spec=$1", hole.get("spec", "Φ8"))
|
||||
spec = _s(hole.get("spec", "Φ8")) or "Φ8"
|
||||
row = await pool.fetchrow("SELECT cycle_time_sec FROM machining_cycle WHERE operation_type='drill' AND spec=$1", spec)
|
||||
if row:
|
||||
total_machining_time_sec += float(row["cycle_time_sec"]) * hole.get("count", 1)
|
||||
|
||||
for hole in tap_holes:
|
||||
row = await pool.fetchrow("SELECT cycle_time_sec FROM machining_cycle WHERE operation_type='tap' AND spec=$1", hole.get("spec", "M8×1.25"))
|
||||
spec = _s(hole.get("spec", "M8×1.25")) or "M8×1.25"
|
||||
row = await pool.fetchrow("SELECT cycle_time_sec FROM machining_cycle WHERE operation_type='tap' AND spec=$1", spec)
|
||||
if row:
|
||||
total_machining_time_sec += float(row["cycle_time_sec"]) * hole.get("count", 1)
|
||||
|
||||
for hole in ream_holes:
|
||||
row = await pool.fetchrow("SELECT cycle_time_sec FROM machining_cycle WHERE operation_type='ream' AND spec=$1", hole.get("spec", "Φ8H7"))
|
||||
spec = _s(hole.get("spec", "Φ8H7")) or "Φ8H7"
|
||||
row = await pool.fetchrow("SELECT cycle_time_sec FROM machining_cycle WHERE operation_type='ream' AND spec=$1", spec)
|
||||
if row:
|
||||
total_machining_time_sec += float(row["cycle_time_sec"]) * hole.get("count", 1)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user