Expose appearance template inspection
This commit is contained in:
@@ -763,6 +763,7 @@ METHODS = [
|
|||||||
{"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": "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": "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."},
|
||||||
{"name": "scd.prepare.rollback", "transport": "POST /rpc", "description": "Remove exactly the rows inserted by one SCD preparation receipt after hash precondition checks. This is intended for controlled test cleanup and never touches active Config/ConfigCAS."},
|
{"name": "scd.prepare.rollback", "transport": "POST /rpc", "description": "Remove exactly the rows inserted by one SCD preparation receipt after hash precondition checks. This is intended for controlled test cleanup and never touches active Config/ConfigCAS."},
|
||||||
{"name": "scd.compare", "transport": "POST /rpc", "description": "Read-only semantic comparison of active and prepared saved-state SCD XML: Config ↔ ConfigSave for base reports and ConfigCAS ↔ ConfigCASSave for extensions. Compares named parameters, datasets, fields, expressions, totals, and variants rather than storage hashes."},
|
{"name": "scd.compare", "transport": "POST /rpc", "description": "Read-only semantic comparison of active and prepared saved-state SCD XML: Config ↔ ConfigSave for base reports and ConfigCAS ↔ ConfigCASSave for extensions. Compares named parameters, datasets, fields, expressions, totals, and variants rather than storage hashes."},
|
||||||
@@ -36070,6 +36071,37 @@ def metadata_object_related(payload: dict[str, Any]) -> dict[str, Any]:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def appearance_inspect(payload: dict[str, Any]) -> dict[str, Any]:
|
||||||
|
"""Read a proven base CommonTemplate appearance XML carrier by public name."""
|
||||||
|
method = "appearance.inspect"
|
||||||
|
base_id_or_error = require_base_id(payload, method)
|
||||||
|
if isinstance(base_id_or_error, dict):
|
||||||
|
return base_id_or_error
|
||||||
|
base_id = base_id_or_error
|
||||||
|
if payload.get("extension") not in {None, ""} or payload.get("extension_guid") not in {None, ""}:
|
||||||
|
return {
|
||||||
|
"schema": "onec_appearance_inspect.v1", "method": method, "status": "unsupported", "base_id": base_id,
|
||||||
|
"diagnostics": {"code": "APPEARANCE_EXTENSION_ROUTE_UNPROVEN", "message": "Only a base CommonTemplate carrier is proven for this reader."},
|
||||||
|
}
|
||||||
|
template = str(payload.get("template") or payload.get("name") or payload.get("guid") or "").strip()
|
||||||
|
if not template:
|
||||||
|
return invalid_argument(method, "template", "template is required as a public CommonTemplate name or GUID.")
|
||||||
|
timeout_seconds = int(payload.get("timeout_seconds") or 60)
|
||||||
|
resolved = get_object("CommonTemplate", template, base_id=base_id, view="effective", limit=2, include_storage=True, include_semantic=False, timeout_seconds=timeout_seconds, table="Config")
|
||||||
|
if resolved.get("status") != "ok" or not isinstance(resolved.get("object"), dict):
|
||||||
|
return {"schema": "onec_appearance_inspect.v1", "method": method, "status": resolved.get("status") or "not_found", "base_id": base_id, "diagnostics": resolved.get("diagnostics") or {}}
|
||||||
|
object_card = resolved["object"]
|
||||||
|
guid = str(object_card.get("guid") or "").strip()
|
||||||
|
if not guid:
|
||||||
|
return {"schema": "onec_appearance_inspect.v1", "method": method, "status": "unresolved", "base_id": base_id, "diagnostics": {"code": "APPEARANCE_GUID_NOT_PROVEN"}}
|
||||||
|
data, _, read_error = read_storage_file_bytes(base_id, "Config", f"{guid}.0", timeout_seconds=min(timeout_seconds, 60))
|
||||||
|
if read_error or data is None:
|
||||||
|
return {"schema": "onec_appearance_inspect.v1", "method": method, "status": "not_found", "base_id": base_id, "diagnostics": (read_error or {}).get("diagnostics") or {"code": "APPEARANCE_PAYLOAD_NOT_FOUND"}}
|
||||||
|
from parser.appearance_payload import inspect_appearance_payload
|
||||||
|
decoded = inspect_appearance_payload(data)
|
||||||
|
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 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"
|
||||||
@@ -70405,6 +70437,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 == "appearance.inspect":
|
||||||
|
return appearance_inspect(payload)
|
||||||
if method == "scd.inspect":
|
if method == "scd.inspect":
|
||||||
return scd_inspect(payload)
|
return scd_inspect(payload)
|
||||||
if method == "scd.prepare":
|
if method == "scd.prepare":
|
||||||
|
|||||||
@@ -265,6 +265,18 @@ def test_appearance_payload_decoder_reads_xml_rules() -> None:
|
|||||||
assert result["diagnostics"]["write"] == "unsupported_until_reverse_codec_fixture"
|
assert result["diagnostics"]["write"] == "unsupported_until_reverse_codec_fixture"
|
||||||
|
|
||||||
|
|
||||||
|
def test_appearance_inspect_resolves_public_common_template(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
|
source = compress_payload('<?xml version="1.0"?><AppearanceTemplate><item><parameter>Заголовок</parameter><value>x</value></item></AppearanceTemplate>'.encode("utf-8"), "raw_deflate")
|
||||||
|
monkeypatch.setattr(adapter_server, "get_object", lambda *_args, **_kwargs: {"status": "ok", "object": {"guid": "a" * 36, "kind": "CommonTemplate", "name": "Оформление"}})
|
||||||
|
monkeypatch.setattr(adapter_server, "read_storage_file_bytes", lambda *_args, **_kwargs: (source, {}, None))
|
||||||
|
|
||||||
|
result = adapter_server.appearance_inspect({"base_id": "upo_test", "template": "Оформление"})
|
||||||
|
|
||||||
|
assert result["status"] == "ok"
|
||||||
|
assert result["template"]["name"] == "Оформление"
|
||||||
|
assert result["appearance"]["items"][0]["parameter"] == "Заголовок"
|
||||||
|
|
||||||
|
|
||||||
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>
|
||||||
|
|||||||
Reference in New Issue
Block a user