From 708d2d87482b9fcf0bae21b56e0851f6580a6d2c Mon Sep 17 00:00:00 2001 From: "Joseph T. French" Date: Sat, 30 May 2026 16:16:31 -0500 Subject: [PATCH] feat(ledger): surface fact provenance; bring IB queries to TS parity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add `provenance` to the factSet selection, and level the GetInformationBlock / ListInformationBlocks queries up to the full envelope standard — rules (incl. ruleTarget / ruleVariables), factSet, verificationResults, and view — so the Python IB reads match the TypeScript client field-for-field. Regenerate the FactSetLite model. --- .../graphql/queries/ledger/__init__.py | 54 ++++++++++++++++++- robosystems_client/models/__init__.py | 2 + robosystems_client/models/fact_set_lite.py | 42 ++++++++++++++- .../models/fact_set_lite_provenance_type_0.py | 47 ++++++++++++++++ 4 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 robosystems_client/models/fact_set_lite_provenance_type_0.py diff --git a/robosystems_client/graphql/queries/ledger/__init__.py b/robosystems_client/graphql/queries/ledger/__init__.py index 5084370..1c02009 100644 --- a/robosystems_client/graphql/queries/ledger/__init__.py +++ b/robosystems_client/graphql/queries/ledger/__init__.py @@ -615,10 +615,35 @@ def parse_mapping_coverage(data: dict[str, Any]) -> dict[str, Any] | None: id elementId value periodStart periodEnd periodType unit factScope factSetId } + rules { + id ruleCategory rulePattern ruleCheckKind ruleExpression + ruleMessage ruleSeverity ruleOrigin + ruleTarget { targetKind targetRefId } + ruleVariables { variableName variableQname } + } + factSet { + id structureId periodStart periodEnd + factsetType entityId reportId provenance + } + verificationResults { + id ruleId structureId factSetId status message + periodStart periodEnd evaluatedAt + } verificationSummary { total passed failed errored skipped byCategory { category total passed failed errored skipped } } + view { + rendering { + rows { + elementId elementQname elementName classification + balanceType values isSubtotal depth + } + periods { start end label } + validation { passed checks failures warnings } + unmappedCount + } + } } } """.strip() @@ -658,10 +683,35 @@ def parse_information_block(data: dict[str, Any]) -> dict[str, Any] | None: id elementId value periodStart periodEnd periodType unit factScope factSetId } + rules { + id ruleCategory rulePattern ruleCheckKind ruleExpression + ruleMessage ruleSeverity ruleOrigin + ruleTarget { targetKind targetRefId } + ruleVariables { variableName variableQname } + } + factSet { + id structureId periodStart periodEnd + factsetType entityId reportId provenance + } + verificationResults { + id ruleId structureId factSetId status message + periodStart periodEnd evaluatedAt + } verificationSummary { total passed failed errored skipped byCategory { category total passed failed errored skipped } } + view { + rendering { + rows { + elementId elementQname elementName classification + balanceType values isSubtotal depth + } + periods { start end label } + validation { passed checks failures warnings } + unmappedCount + } + } } } """.strip() @@ -836,10 +886,12 @@ def parse_report(data: dict[str, Any]) -> dict[str, Any] | None: rules { id ruleCategory rulePattern ruleCheckKind ruleExpression ruleMessage ruleSeverity ruleOrigin + ruleTarget { targetKind targetRefId } + ruleVariables { variableName variableQname } } factSet { id structureId periodStart periodEnd - factsetType entityId reportId + factsetType entityId reportId provenance } verificationResults { id ruleId structureId factSetId status message diff --git a/robosystems_client/models/__init__.py b/robosystems_client/models/__init__.py index 64b60b5..f25c20a 100644 --- a/robosystems_client/models/__init__.py +++ b/robosystems_client/models/__init__.py @@ -188,6 +188,7 @@ ) from .fact_lite import FactLite from .fact_set_lite import FactSetLite +from .fact_set_lite_provenance_type_0 import FactSetLiteProvenanceType0 from .file_info import FileInfo from .file_layer_status import FileLayerStatus from .file_report_request import FileReportRequest @@ -840,6 +841,7 @@ "ExecuteEventBlockResponseQbErrorType0", "FactLite", "FactSetLite", + "FactSetLiteProvenanceType0", "FileInfo", "FileLayerStatus", "FileReportRequest", diff --git a/robosystems_client/models/fact_set_lite.py b/robosystems_client/models/fact_set_lite.py index 55d2b02..f77e1d5 100644 --- a/robosystems_client/models/fact_set_lite.py +++ b/robosystems_client/models/fact_set_lite.py @@ -2,7 +2,7 @@ import datetime from collections.abc import Mapping -from typing import Any, TypeVar, cast +from typing import TYPE_CHECKING, Any, TypeVar, cast from attrs import define as _attrs_define from attrs import field as _attrs_field @@ -10,6 +10,10 @@ from ..types import UNSET, Unset +if TYPE_CHECKING: + from ..models.fact_set_lite_provenance_type_0 import FactSetLiteProvenanceType0 + + T = TypeVar("T", bound="FactSetLite") @@ -32,6 +36,9 @@ class FactSetLite: period_start (datetime.date | None | Unset): report_id (None | str | Unset): Back-pointer to the ``reports`` table while ``report_id`` still lives on facts. Drops out once the retirement migration lands. + provenance (FactSetLiteProvenanceType0 | None | Unset): Typed ``FactProvenance`` descriptor (discriminated on + ``origin``: pivot | schedule | derived | asserted) recording how this FactSet's facts were constructed. Surfaced + as JSON, mirroring how mechanics is exposed. Null for pre-feature historical FactSets. """ id: str @@ -41,9 +48,12 @@ class FactSetLite: structure_id: None | str | Unset = UNSET period_start: datetime.date | None | Unset = UNSET report_id: None | str | Unset = UNSET + provenance: FactSetLiteProvenanceType0 | None | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: + from ..models.fact_set_lite_provenance_type_0 import FactSetLiteProvenanceType0 + id = self.id period_end = self.period_end.isoformat() @@ -72,6 +82,14 @@ def to_dict(self) -> dict[str, Any]: else: report_id = self.report_id + provenance: dict[str, Any] | None | Unset + if isinstance(self.provenance, Unset): + provenance = UNSET + elif isinstance(self.provenance, FactSetLiteProvenanceType0): + provenance = self.provenance.to_dict() + else: + provenance = self.provenance + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -88,11 +106,15 @@ def to_dict(self) -> dict[str, Any]: field_dict["period_start"] = period_start if report_id is not UNSET: field_dict["report_id"] = report_id + if provenance is not UNSET: + field_dict["provenance"] = provenance return field_dict @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.fact_set_lite_provenance_type_0 import FactSetLiteProvenanceType0 + d = dict(src_dict) id = d.pop("id") @@ -137,6 +159,23 @@ def _parse_report_id(data: object) -> None | str | Unset: report_id = _parse_report_id(d.pop("report_id", UNSET)) + def _parse_provenance(data: object) -> FactSetLiteProvenanceType0 | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + provenance_type_0 = FactSetLiteProvenanceType0.from_dict(data) + + return provenance_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(FactSetLiteProvenanceType0 | None | Unset, data) + + provenance = _parse_provenance(d.pop("provenance", UNSET)) + fact_set_lite = cls( id=id, period_end=period_end, @@ -145,6 +184,7 @@ def _parse_report_id(data: object) -> None | str | Unset: structure_id=structure_id, period_start=period_start, report_id=report_id, + provenance=provenance, ) fact_set_lite.additional_properties = d diff --git a/robosystems_client/models/fact_set_lite_provenance_type_0.py b/robosystems_client/models/fact_set_lite_provenance_type_0.py new file mode 100644 index 0000000..3ac4fd4 --- /dev/null +++ b/robosystems_client/models/fact_set_lite_provenance_type_0.py @@ -0,0 +1,47 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="FactSetLiteProvenanceType0") + + +@_attrs_define +class FactSetLiteProvenanceType0: + """ """ + + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + fact_set_lite_provenance_type_0 = cls() + + fact_set_lite_provenance_type_0.additional_properties = d + return fact_set_lite_provenance_type_0 + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties