Add confirmed report component inspection

This commit is contained in:
2026-08-14 13:03:43 +03:00
parent c6384ff753
commit ae11b5e227
2 changed files with 50 additions and 0 deletions
+33
View File
@@ -762,6 +762,7 @@ METHODS = [
{"name": "metadata.object.components", "transport": "POST /rpc", "description": "Read-only confirmed component graph for one metadata object. Returns only modules, forms, templates, and SCD nodes confirmed by the existing live-SQL decoders, with public child selectors and explicit unresolved areas. It never infers absent children from an object kind."}, {"name": "metadata.object.components", "transport": "POST /rpc", "description": "Read-only confirmed component graph for one metadata object. Returns only modules, forms, templates, and SCD nodes confirmed by the existing live-SQL decoders, with public child selectors and explicit unresolved areas. It never infers absent children from an object kind."},
{"name": "metadata.object.modules", "transport": "POST /rpc", "description": "1C-facing BSL module list for a metadata object, including owned form modules. Exact extension objects are resolved from public kind/name or ref through a live-validated route cache. include_storage must be a JSON boolean true/false, string values are invalid. Physical module ids are hidden unless include_storage=true."}, {"name": "metadata.object.modules", "transport": "POST /rpc", "description": "1C-facing BSL module list for a metadata object, including owned form modules. Exact extension objects are resolved from public kind/name or ref through a live-validated route cache. include_storage must be a JSON boolean true/false, string values are invalid. Physical module ids are hidden unless include_storage=true."},
{"name": "metadata.object.related", "transport": "POST /rpc", "description": "1C-facing related metadata objects such as forms and templates. Physical record paths are hidden unless include_storage=true."}, {"name": "metadata.object.related", "transport": "POST /rpc", "description": "1C-facing related metadata objects such as forms and templates. Physical record paths are hidden unless include_storage=true."},
{"name": "report.inspect", "transport": "POST /rpc", "description": "Read-only aggregate of one report's confirmed modules, forms, templates and Data Composition Schemas. Does not infer an SCD from a same-named form or stream."},
{"name": "scd.inspect", "transport": "POST /rpc", "description": "Read-only inspection entry point for a report Data Composition Schema. Resolves a base report from Config or an extension report from ConfigCAS by public names, and returns partial evidence instead of inventing undecoded parameters, datasets, resources, or variants."}, {"name": "scd.inspect", "transport": "POST /rpc", "description": "Read-only inspection entry point for a report Data Composition Schema. Resolves a base report from Config or an extension report from ConfigCAS by public names, and returns partial evidence instead of inventing undecoded parameters, datasets, resources, or variants."},
{"name": "appearance.inspect", "transport": "POST /rpc", "description": "Read-only inspection of a base CommonTemplate whose payload is confirmed as AppearanceTemplate XML. Returns XML-backed appearance rules; no write route is exposed."}, {"name": "appearance.inspect", "transport": "POST /rpc", "description": "Read-only inspection of a base CommonTemplate whose payload is confirmed as AppearanceTemplate XML. Returns XML-backed appearance rules; no write route is exposed."},
{"name": "scd.prepare", "transport": "POST /rpc", "description": "Prepare the complete SQL saved-state file set required for one report SCD. For base reports it includes both report files and the separately stored Template payload group, while keeping SQL file identifiers internal."}, {"name": "scd.prepare", "transport": "POST /rpc", "description": "Prepare the complete SQL saved-state file set required for one report SCD. For base reports it includes both report files and the separately stored Template payload group, while keeping SQL file identifiers internal."},
@@ -36102,6 +36103,36 @@ def appearance_inspect(payload: dict[str, Any]) -> dict[str, Any]:
return {"schema": "onec_appearance_inspect.v1", "method": method, "status": decoded.get("status"), "base_id": base_id, "template": public_metadata_row(object_card), "appearance": decoded, "activation_state": "working_not_runtime_applied"} return {"schema": "onec_appearance_inspect.v1", "method": method, "status": decoded.get("status"), "base_id": base_id, "template": public_metadata_row(object_card), "appearance": decoded, "activation_state": "working_not_runtime_applied"}
def report_inspect(payload: dict[str, Any]) -> dict[str, Any]:
"""Return the confirmed component graph of a report without filling gaps."""
method = "report.inspect"
base_id_or_error = require_base_id(payload, method)
if isinstance(base_id_or_error, dict):
return base_id_or_error
report = str(payload.get("report") or payload.get("name") or "").strip()
if not report:
return invalid_argument(method, "report", "report is required as a public 1C report name.")
component_payload = {"base_id": base_id_or_error, "kind": "Report", "name": report, "include_storage": False, "timeout_seconds": int(payload.get("timeout_seconds") or 60)}
for key in ("extension", "extension_guid"):
if payload.get(key) not in {None, ""}:
component_payload[key] = payload[key]
components_result = metadata_object_components(component_payload)
if not isinstance(components_result.get("object"), dict):
return {"schema": "onec_report_inspect.v1", "method": method, "status": components_result.get("status") or "not_found", "base_id": base_id_or_error, "unresolved": components_result.get("unresolved") or [], "diagnostics": components_result.get("diagnostics") or {}}
components = [item for item in components_result.get("components") or [] if isinstance(item, dict)]
return {
"schema": "onec_report_inspect.v1", "method": method, "status": "ok", "base_id": base_id_or_error,
"report": public_metadata_row(components_result["object"]),
"components": components,
"scd": [item for item in components if item.get("component_kind") == "scd"],
"templates": [item for item in components if item.get("component_kind") in {"scd", "template"}],
"forms": [item for item in components if item.get("component_kind") == "form"],
"modules": [item for item in components if item.get("component_kind") == "module"],
"unresolved": components_result.get("unresolved") or [],
"diagnostics": {"rule": "Only components proven by the individual live-SQL readers are included; a form is never promoted to an SCD by name."},
}
def scd_inspect(payload: dict[str, Any]) -> dict[str, Any]: def scd_inspect(payload: dict[str, Any]) -> dict[str, Any]:
"""Resolve and decode one report SCD from its SQL ConfigCAS payload.""" """Resolve and decode one report SCD from its SQL ConfigCAS payload."""
method = "scd.inspect" method = "scd.inspect"
@@ -70437,6 +70468,8 @@ def call_method_impl(method: str, payload: dict[str, Any] | None) -> dict[str, A
return metadata_object_modules(payload) return metadata_object_modules(payload)
if method == "metadata.object.related": if method == "metadata.object.related":
return metadata_object_related(payload) return metadata_object_related(payload)
if method == "report.inspect":
return report_inspect(payload)
if method == "appearance.inspect": if method == "appearance.inspect":
return appearance_inspect(payload) return appearance_inspect(payload)
if method == "scd.inspect": if method == "scd.inspect":
+17
View File
@@ -280,6 +280,23 @@ def test_appearance_inspect_resolves_public_common_template(monkeypatch: pytest.
assert result["appearance"]["items"][0]["parameter"] == "Заголовок" assert result["appearance"]["items"][0]["parameter"] == "Заголовок"
def test_report_inspect_keeps_forms_separate_from_scd(monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(adapter_server, "metadata_object_components", lambda _payload: {
"status": "ok", "object": {"kind": "Report", "name": "Продажи", "guid": "r" * 36},
"components": [
{"component_kind": "form", "name": "ОсновнаяСхемаКомпоновкиДанных"},
{"component_kind": "scd", "name": "ОсновнаяСхема", "guid": "s" * 36},
], "unresolved": [{"area": "templates", "status": "partial"}],
})
result = adapter_server.report_inspect({"base_id": "upo_test", "report": "Продажи"})
assert result["status"] == "ok"
assert [item["name"] for item in result["forms"]] == ["ОсновнаяСхемаКомпоновкиДанных"]
assert [item["name"] for item in result["scd"]] == ["ОсновнаяСхема"]
assert result["unresolved"][0]["area"] == "templates"
def test_scd_scalar_patch_preserves_platform_prefix_and_trailer() -> None: def test_scd_scalar_patch_preserves_platform_prefix_and_trailer() -> None:
xml = """<?xml version="1.0" encoding="UTF-8"?> xml = """<?xml version="1.0" encoding="UTF-8"?>
<SchemaFile><dataCompositionSchema> <SchemaFile><dataCompositionSchema>