"""Cached platform constraints shared by SUPER authoring and generic execution.""" from fastapi import HTTPException from ..catalog.research_metadata import ResearchMetadata async def validate_settings(db, values): """Reject known unsupported values; absent metadata is explicitly unknown, never approved.""" snapshot = await ResearchMetadata(db).get("settings") rows = snapshot["content"].get("items", []) if not snapshot["fetched_at"] or not rows: return {"status": "unknown", "reason": "未缓存平台设置"} incomplete = False for settings in values: value = settings.model_dump() if hasattr(settings, "model_dump") else settings matches = [r for r in rows if all(r.get(k) == value.get(v) for k, v in ( ("instrument_type", "instrumentType"), ("region", "region"), ("universe", "universe"), ("delay", "delay")))] if not matches: raise HTTPException(422, "平台设置快照不支持当前 SUPER 地区 / Universe / Delay 组合") failures = [] valid = False for row in matches: failed = [] if row.get("neutralizations") and value["neutralization"] not in row["neutralizations"]: failed.append("neutralization") for key, field in row.get("fields", {}).items(): if key not in value: continue current = value[key] if "choices" in field and current not in field["choices"]: failed.append(key) if type(current) in (int, float) and ( ("minimum" in field and current < field["minimum"]) or ("maximum" in field and current > field["maximum"])): failed.append(key) if not failed: valid = True incomplete |= any(not row.get("fields", {}).get(key) for key in ("selectionLimit", "selectionHandling", "componentActivation")) break failures.extend(failed) if not valid: raise HTTPException(422, "平台设置快照不支持 SUPER 参数:" + "、".join(sorted(set(failures)))) return {"status": "partial" if incomplete else "cached", "fetched_at": snapshot["fetched_at"], "reason": "部分 SUPER 设置范围未提供" if incomplete else "仅按缓存校验,仍需平台执行验证"}