chore(v2): 从兴邦预审v2白名单抽取独立可运行基座
按 docs/v2/05-implementation-plan.md §1 候选迁移表与 claude_use/T00 白名单, 从 55e2cdb 抽取 224 个文件(2.48 MB)到独立目录 F:/mini-OpenClaw-v2。 - 排除:凭据(.env/server-deploy.conf/旧DELIVERY.md)、运行数据(xingbang_data 等 4 个 SQLite)、依赖(venv/node_modules 符号链接)、归档(_backup*/test-evidence/ ori_file)、Office 临时文件 - 目标目录独立 git 仓库,初始恢复点;Gitea 远程与分支待 OQ-06 Q2 定案 - 未部署、未启动服务、未调用模型 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
"""Same read-only query/alignment contract for mock data and approved SQL sources."""
|
||||
from copy import deepcopy
|
||||
from decimal import Decimal
|
||||
from api import risk_agent_config as catalog
|
||||
from services.assistant_store import uid, digest
|
||||
from services.assistant_materials import NUMERIC, scalar
|
||||
from services.skill_executor import number
|
||||
from api.risk_agent_alignment import MONEY_FIELDS, SCALE
|
||||
|
||||
|
||||
def load_catalog():
|
||||
with catalog._db() as db:
|
||||
return {kind: catalog._all(db, kind) for kind in catalog.SEED}
|
||||
|
||||
|
||||
def read_cards(project, components):
|
||||
values, sources = deepcopy(project["values"]), {}
|
||||
for field, refs in project["sources"].items():
|
||||
sources[field] = [r for r in refs if r["id"] == project["selected_sources"].get(field)]
|
||||
datasets, errors = [], []
|
||||
if project.get("pending_candidates"):
|
||||
errors.append({"card_id": "materials", "message": "存在尚未人工确认的材料候选,本次仍使用已确认事实"})
|
||||
samples = {}
|
||||
for (table, rows), mapping in zip(catalog.SAMPLES.items(), catalog.MAPPINGS):
|
||||
row = {key: None for key in rows[0]}
|
||||
row["project_id"] = project["id"]
|
||||
for field, column in mapping.items():
|
||||
row[column] = values.get(field)
|
||||
row.update(project_id=project["id"])
|
||||
if table == "project":
|
||||
row["customer_name"] = project["customer"]
|
||||
if table == "finance":
|
||||
row.update(period=project.get("period", "2025"), scope=project.get("scope", "合并"))
|
||||
samples[table] = [row]
|
||||
for card in components.get("legacy_cards", []):
|
||||
connection = next(c for c in components["legacy_connections"] if c["id"] == card["connection"])
|
||||
if connection.get("data_domain", "demo" if connection.get("type") == "demo" else "production") != project["data_domain"]:
|
||||
raise ValueError("演示数据与正式数据源不可混用")
|
||||
try:
|
||||
rows = catalog.query_card(card, connection, project["id"], demo_samples=samples, exact_decimals=True)
|
||||
records, selected = catalog.align(card, rows, project["id"], project.get("period", "2025"))
|
||||
datasets.append({"card_id": card["id"], "name": card["name"], "version": card["version"], "records": records, "row_hash": digest(rows)})
|
||||
if selected is None:
|
||||
errors.append({"card_id": card["id"], "message": "多期或多口径记录未选择,未合并计算"})
|
||||
continue
|
||||
for field, column in card.get("mapping", {}).items():
|
||||
raw = selected["values"].get(field)
|
||||
if field in NUMERIC:
|
||||
raw = selected["raw"].get(column)
|
||||
unit = card.get("field_units", {}).get(field, card.get("unit") if field in MONEY_FIELDS else None)
|
||||
if raw is not None and unit:
|
||||
raw = number(raw) * SCALE[unit]
|
||||
raw = scalar(field, raw)
|
||||
# Mock SQL uses the actual parsed fixture values; retain their file locators.
|
||||
if connection.get("type") == "demo" and field in sources:
|
||||
same = values.get(field) == raw
|
||||
if field in NUMERIC and values.get(field) is not None and raw is not None:
|
||||
same = number(values[field]) == number(raw)
|
||||
if not same:
|
||||
values[field] = None
|
||||
errors.append({"card_id": card["id"], "message": field + "映射结果与原始材料冲突"})
|
||||
continue
|
||||
ref = {"id": uid("ev"), "project_id": project["id"], "field": field, "value": raw,
|
||||
"source": card["name"], "locator": "数据卡字段 " + column, "card_id": card["id"], "version": card["version"],
|
||||
"period": selected["period"], "scope": selected["scope"], "unit": selected["units"].get(field), "currency": card.get("currency", "CNY")}
|
||||
same = values.get(field) == raw
|
||||
if field in NUMERIC and values.get(field) is not None and raw is not None:
|
||||
same = number(values[field]) == number(raw)
|
||||
if field in values and not same:
|
||||
values[field] = None
|
||||
errors.append({"card_id": card["id"], "message": field + "多来源冲突,请人工确认"})
|
||||
else:
|
||||
values[field] = raw
|
||||
sources.setdefault(field, []).append(ref)
|
||||
except Exception as exc:
|
||||
# No connection strings/credentials in project-facing diagnostics.
|
||||
errors.append({"card_id": card["id"], "message": "数据卡读取或口径校验失败", "error_type": type(exc).__name__})
|
||||
return values, sources, datasets, errors
|
||||
Reference in New Issue
Block a user