From 50f6267a2ea8e15d596c05981164368a0212c020 Mon Sep 17 00:00:00 2001 From: "Joseph T. French" Date: Thu, 23 Jul 2026 00:41:04 -0500 Subject: [PATCH] feat(models): regen SDK for the chart view arm + metric item_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regenerates the client from the M-2 + A-2 OpenAPI spec. New: ChartLite / ChartPanelLite / ChartSeriesLite on the envelope's view arm; item_type on ElementLite / RenderingRowLite. The regen also catches the client up to the compute-metrics operation surface (request/response + envelope) now that it's in the spec. OpenAPI-driven — no hand edits. --- .../extensions_robo_ledger/compute_metrics.py | 298 ++++++++++++++++++ .../create_taxonomy_block.py | 44 +-- .../extensions_robo_ledger/evaluate_rules.py | 8 +- .../update_taxonomy_block.py | 12 +- robosystems_client/models/__init__.py | 26 ++ robosystems_client/models/chart_lite.py | 85 +++++ robosystems_client/models/chart_panel_lite.py | 135 ++++++++ .../models/chart_series_lite.py | 85 +++++ .../models/compute_metrics_request.py | 133 ++++++++ .../models/compute_metrics_response.py | 152 +++++++++ .../models/computed_metric_lite.py | 145 +++++++++ robosystems_client/models/element_lite.py | 21 ++ .../models/information_block_envelope.py | 4 +- ...ation_envelope_compute_metrics_response.py | 158 ++++++++++ ...nvelope_compute_metrics_response_status.py | 10 + .../models/rendering_row_lite.py | 21 ++ .../models/skipped_metric_lite.py | 107 +++++++ .../models/structure_update_patch.py | 58 +++- ...update_patch_concept_arrangement_type_0.py | 22 ++ .../models/taxonomy_block_rule_request.py | 4 +- ...axonomy_block_rule_request_rule_pattern.py | 1 + robosystems_client/models/view_projections.py | 37 ++- 22 files changed, 1529 insertions(+), 37 deletions(-) create mode 100644 robosystems_client/api/extensions_robo_ledger/compute_metrics.py create mode 100644 robosystems_client/models/chart_lite.py create mode 100644 robosystems_client/models/chart_panel_lite.py create mode 100644 robosystems_client/models/chart_series_lite.py create mode 100644 robosystems_client/models/compute_metrics_request.py create mode 100644 robosystems_client/models/compute_metrics_response.py create mode 100644 robosystems_client/models/computed_metric_lite.py create mode 100644 robosystems_client/models/operation_envelope_compute_metrics_response.py create mode 100644 robosystems_client/models/operation_envelope_compute_metrics_response_status.py create mode 100644 robosystems_client/models/skipped_metric_lite.py create mode 100644 robosystems_client/models/structure_update_patch_concept_arrangement_type_0.py diff --git a/robosystems_client/api/extensions_robo_ledger/compute_metrics.py b/robosystems_client/api/extensions_robo_ledger/compute_metrics.py new file mode 100644 index 0000000..1d03d4b --- /dev/null +++ b/robosystems_client/api/extensions_robo_ledger/compute_metrics.py @@ -0,0 +1,298 @@ +from http import HTTPStatus +from typing import Any +from urllib.parse import quote + +import httpx + +from ... import errors +from ...client import AuthenticatedClient, Client +from ...models.compute_metrics_request import ComputeMetricsRequest +from ...models.error_response import ErrorResponse +from ...models.operation_envelope_compute_metrics_response import ( + OperationEnvelopeComputeMetricsResponse, +) +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + graph_id: str, + *, + body: ComputeMetricsRequest, + idempotency_key: None | str | Unset = UNSET, +) -> dict[str, Any]: + headers: dict[str, Any] = {} + if not isinstance(idempotency_key, Unset): + headers["Idempotency-Key"] = idempotency_key + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/extensions/roboledger/{graph_id}/operations/compute-metrics".format( + graph_id=quote(str(graph_id), safe=""), + ), + } + + _kwargs["json"] = body.to_dict() + + headers["Content-Type"] = "application/json" + + _kwargs["headers"] = headers + return _kwargs + + +def _parse_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> ErrorResponse | OperationEnvelopeComputeMetricsResponse | None: + if response.status_code == 200: + response_200 = OperationEnvelopeComputeMetricsResponse.from_dict(response.json()) + + return response_200 + + if response.status_code == 400: + response_400 = ErrorResponse.from_dict(response.json()) + + return response_400 + + if response.status_code == 401: + response_401 = ErrorResponse.from_dict(response.json()) + + return response_401 + + if response.status_code == 403: + response_403 = ErrorResponse.from_dict(response.json()) + + return response_403 + + if response.status_code == 404: + response_404 = ErrorResponse.from_dict(response.json()) + + return response_404 + + if response.status_code == 409: + response_409 = ErrorResponse.from_dict(response.json()) + + return response_409 + + if response.status_code == 422: + response_422 = ErrorResponse.from_dict(response.json()) + + return response_422 + + if response.status_code == 429: + response_429 = ErrorResponse.from_dict(response.json()) + + return response_429 + + if response.status_code == 500: + response_500 = ErrorResponse.from_dict(response.json()) + + return response_500 + + if client.raise_on_unexpected_status: + raise errors.UnexpectedStatus(response.status_code, response.content) + else: + return None + + +def _build_response( + *, client: AuthenticatedClient | Client, response: httpx.Response +) -> Response[ErrorResponse | OperationEnvelopeComputeMetricsResponse]: + return Response( + status_code=HTTPStatus(response.status_code), + content=response.content, + headers=response.headers, + parsed=_parse_response(client=client, response=response), + ) + + +def sync_detailed( + graph_id: str, + *, + client: AuthenticatedClient, + body: ComputeMetricsRequest, + idempotency_key: None | str | Unset = UNSET, +) -> Response[ErrorResponse | OperationEnvelopeComputeMetricsResponse]: + """Compute Metrics for a Metric Block + + Resolves the Derive rules scoped to a metric block (block_type='metric'), binds each rule's operands + to the entity's most recent persisted report facts at period_end, evaluates, and upserts the + period's standing factset_type='metric' FactSet — one per (structure, entity, period_end), so + successive runs accumulate the time series and re-running a period replaces its values. Metrics with + missing operands or undefined ratios are skipped with a reason, never errored. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (ComputeMetricsRequest): Request body for the ``compute-metrics`` operation. + + Resolves the ``Derive`` rules scoped to the metric block, binds each + rule's operands to the entity's most recent persisted report facts at + ``period_end``, evaluates, and upserts the period's standing + ``factset_type='metric'`` FactSet (re-running a period replaces its + facts). One standing FactSet per (structure, entity, period_end) — the + accumulating time series. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | OperationEnvelopeComputeMetricsResponse] + """ + + kwargs = _get_kwargs( + graph_id=graph_id, + body=body, + idempotency_key=idempotency_key, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + graph_id: str, + *, + client: AuthenticatedClient, + body: ComputeMetricsRequest, + idempotency_key: None | str | Unset = UNSET, +) -> ErrorResponse | OperationEnvelopeComputeMetricsResponse | None: + """Compute Metrics for a Metric Block + + Resolves the Derive rules scoped to a metric block (block_type='metric'), binds each rule's operands + to the entity's most recent persisted report facts at period_end, evaluates, and upserts the + period's standing factset_type='metric' FactSet — one per (structure, entity, period_end), so + successive runs accumulate the time series and re-running a period replaces its values. Metrics with + missing operands or undefined ratios are skipped with a reason, never errored. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (ComputeMetricsRequest): Request body for the ``compute-metrics`` operation. + + Resolves the ``Derive`` rules scoped to the metric block, binds each + rule's operands to the entity's most recent persisted report facts at + ``period_end``, evaluates, and upserts the period's standing + ``factset_type='metric'`` FactSet (re-running a period replaces its + facts). One standing FactSet per (structure, entity, period_end) — the + accumulating time series. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | OperationEnvelopeComputeMetricsResponse + """ + + return sync_detailed( + graph_id=graph_id, + client=client, + body=body, + idempotency_key=idempotency_key, + ).parsed + + +async def asyncio_detailed( + graph_id: str, + *, + client: AuthenticatedClient, + body: ComputeMetricsRequest, + idempotency_key: None | str | Unset = UNSET, +) -> Response[ErrorResponse | OperationEnvelopeComputeMetricsResponse]: + """Compute Metrics for a Metric Block + + Resolves the Derive rules scoped to a metric block (block_type='metric'), binds each rule's operands + to the entity's most recent persisted report facts at period_end, evaluates, and upserts the + period's standing factset_type='metric' FactSet — one per (structure, entity, period_end), so + successive runs accumulate the time series and re-running a period replaces its values. Metrics with + missing operands or undefined ratios are skipped with a reason, never errored. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (ComputeMetricsRequest): Request body for the ``compute-metrics`` operation. + + Resolves the ``Derive`` rules scoped to the metric block, binds each + rule's operands to the entity's most recent persisted report facts at + ``period_end``, evaluates, and upserts the period's standing + ``factset_type='metric'`` FactSet (re-running a period replaces its + facts). One standing FactSet per (structure, entity, period_end) — the + accumulating time series. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + Response[ErrorResponse | OperationEnvelopeComputeMetricsResponse] + """ + + kwargs = _get_kwargs( + graph_id=graph_id, + body=body, + idempotency_key=idempotency_key, + ) + + response = await client.get_async_httpx_client().request(**kwargs) + + return _build_response(client=client, response=response) + + +async def asyncio( + graph_id: str, + *, + client: AuthenticatedClient, + body: ComputeMetricsRequest, + idempotency_key: None | str | Unset = UNSET, +) -> ErrorResponse | OperationEnvelopeComputeMetricsResponse | None: + """Compute Metrics for a Metric Block + + Resolves the Derive rules scoped to a metric block (block_type='metric'), binds each rule's operands + to the entity's most recent persisted report facts at period_end, evaluates, and upserts the + period's standing factset_type='metric' FactSet — one per (structure, entity, period_end), so + successive runs accumulate the time series and re-running a period replaces its values. Metrics with + missing operands or undefined ratios are skipped with a reason, never errored. + + **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours + return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. + + Args: + graph_id (str): + idempotency_key (None | str | Unset): + body (ComputeMetricsRequest): Request body for the ``compute-metrics`` operation. + + Resolves the ``Derive`` rules scoped to the metric block, binds each + rule's operands to the entity's most recent persisted report facts at + ``period_end``, evaluates, and upserts the period's standing + ``factset_type='metric'`` FactSet (re-running a period replaces its + facts). One standing FactSet per (structure, entity, period_end) — the + accumulating time series. + + Raises: + errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. + httpx.TimeoutException: If the request takes longer than Client.timeout. + + Returns: + ErrorResponse | OperationEnvelopeComputeMetricsResponse + """ + + return ( + await asyncio_detailed( + graph_id=graph_id, + client=client, + body=body, + idempotency_key=idempotency_key, + ) + ).parsed diff --git a/robosystems_client/api/extensions_robo_ledger/create_taxonomy_block.py b/robosystems_client/api/extensions_robo_ledger/create_taxonomy_block.py index 298aa0d..b087971 100644 --- a/robosystems_client/api/extensions_robo_ledger/create_taxonomy_block.py +++ b/robosystems_client/api/extensions_robo_ledger/create_taxonomy_block.py @@ -115,11 +115,12 @@ def sync_detailed( Create a taxonomy block atomically: one envelope carrying the taxonomy row plus its structures, elements, associations, and rules. Dispatches by `taxonomy_type` — `chart_of_accounts` (declarative - tenant CoA) is supported; `reporting_extension` / `custom_ontology` / `reporting_standard` are not - yet implemented. NOT the path for a functional close schedule: a structure with - block_type='schedule' here is a bare ontology row with none of the schedule machinery (per-period - facts, schedule_entry_due obligations, closing-entry generator). To create a working schedule use - create-information-block(block_type='schedule'). + tenant CoA), `reporting_extension`, and `custom_ontology` are supported; `reporting_standard` is + library-origin (501). `reporting_extension` / `custom_ontology` authoring may be disabled per + environment (TAXONOMY_AUTHORING_ENABLED) — disabled surfaces 403. NOT the path for a functional + close schedule: a structure with block_type='schedule' here is a bare ontology row with none of the + schedule machinery (per-period facts, schedule_entry_due obligations, closing-entry generator). To + create a working schedule use create-information-block(block_type='schedule'). **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. @@ -171,11 +172,12 @@ def sync( Create a taxonomy block atomically: one envelope carrying the taxonomy row plus its structures, elements, associations, and rules. Dispatches by `taxonomy_type` — `chart_of_accounts` (declarative - tenant CoA) is supported; `reporting_extension` / `custom_ontology` / `reporting_standard` are not - yet implemented. NOT the path for a functional close schedule: a structure with - block_type='schedule' here is a bare ontology row with none of the schedule machinery (per-period - facts, schedule_entry_due obligations, closing-entry generator). To create a working schedule use - create-information-block(block_type='schedule'). + tenant CoA), `reporting_extension`, and `custom_ontology` are supported; `reporting_standard` is + library-origin (501). `reporting_extension` / `custom_ontology` authoring may be disabled per + environment (TAXONOMY_AUTHORING_ENABLED) — disabled surfaces 403. NOT the path for a functional + close schedule: a structure with block_type='schedule' here is a bare ontology row with none of the + schedule machinery (per-period facts, schedule_entry_due obligations, closing-entry generator). To + create a working schedule use create-information-block(block_type='schedule'). **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. @@ -222,11 +224,12 @@ async def asyncio_detailed( Create a taxonomy block atomically: one envelope carrying the taxonomy row plus its structures, elements, associations, and rules. Dispatches by `taxonomy_type` — `chart_of_accounts` (declarative - tenant CoA) is supported; `reporting_extension` / `custom_ontology` / `reporting_standard` are not - yet implemented. NOT the path for a functional close schedule: a structure with - block_type='schedule' here is a bare ontology row with none of the schedule machinery (per-period - facts, schedule_entry_due obligations, closing-entry generator). To create a working schedule use - create-information-block(block_type='schedule'). + tenant CoA), `reporting_extension`, and `custom_ontology` are supported; `reporting_standard` is + library-origin (501). `reporting_extension` / `custom_ontology` authoring may be disabled per + environment (TAXONOMY_AUTHORING_ENABLED) — disabled surfaces 403. NOT the path for a functional + close schedule: a structure with block_type='schedule' here is a bare ontology row with none of the + schedule machinery (per-period facts, schedule_entry_due obligations, closing-entry generator). To + create a working schedule use create-information-block(block_type='schedule'). **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. @@ -276,11 +279,12 @@ async def asyncio( Create a taxonomy block atomically: one envelope carrying the taxonomy row plus its structures, elements, associations, and rules. Dispatches by `taxonomy_type` — `chart_of_accounts` (declarative - tenant CoA) is supported; `reporting_extension` / `custom_ontology` / `reporting_standard` are not - yet implemented. NOT the path for a functional close schedule: a structure with - block_type='schedule' here is a bare ontology row with none of the schedule machinery (per-period - facts, schedule_entry_due obligations, closing-entry generator). To create a working schedule use - create-information-block(block_type='schedule'). + tenant CoA), `reporting_extension`, and `custom_ontology` are supported; `reporting_standard` is + library-origin (501). `reporting_extension` / `custom_ontology` authoring may be disabled per + environment (TAXONOMY_AUTHORING_ENABLED) — disabled surfaces 403. NOT the path for a functional + close schedule: a structure with block_type='schedule' here is a bare ontology row with none of the + schedule machinery (per-period facts, schedule_entry_due obligations, closing-entry generator). To + create a working schedule use create-information-block(block_type='schedule'). **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. diff --git a/robosystems_client/api/extensions_robo_ledger/evaluate_rules.py b/robosystems_client/api/extensions_robo_ledger/evaluate_rules.py index d8eb6cc..5526c12 100644 --- a/robosystems_client/api/extensions_robo_ledger/evaluate_rules.py +++ b/robosystems_client/api/extensions_robo_ledger/evaluate_rules.py @@ -116,7 +116,7 @@ def sync_detailed( Runs every rule targeting the given structure (plus element- and association-scoped rules for the structure's atoms), binds $Variable references to in-scope facts via qname lookup, writes one VerificationResult row per rule, and returns the results plus a status-keyed summary. Decoding mode, - 5 patterns (EqualTo, RollUp, RollForward, Exists, CoExists). + 6 patterns (EqualTo, RollUp, RollForward, SumEquals, Exists, CoExists). **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. @@ -168,7 +168,7 @@ def sync( Runs every rule targeting the given structure (plus element- and association-scoped rules for the structure's atoms), binds $Variable references to in-scope facts via qname lookup, writes one VerificationResult row per rule, and returns the results plus a status-keyed summary. Decoding mode, - 5 patterns (EqualTo, RollUp, RollForward, Exists, CoExists). + 6 patterns (EqualTo, RollUp, RollForward, SumEquals, Exists, CoExists). **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. @@ -215,7 +215,7 @@ async def asyncio_detailed( Runs every rule targeting the given structure (plus element- and association-scoped rules for the structure's atoms), binds $Variable references to in-scope facts via qname lookup, writes one VerificationResult row per rule, and returns the results plus a status-keyed summary. Decoding mode, - 5 patterns (EqualTo, RollUp, RollForward, Exists, CoExists). + 6 patterns (EqualTo, RollUp, RollForward, SumEquals, Exists, CoExists). **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. @@ -265,7 +265,7 @@ async def asyncio( Runs every rule targeting the given structure (plus element- and association-scoped rules for the structure's atoms), binds $Variable references to in-scope facts via qname lookup, writes one VerificationResult row per rule, and returns the results plus a status-keyed summary. Decoding mode, - 5 patterns (EqualTo, RollUp, RollForward, Exists, CoExists). + 6 patterns (EqualTo, RollUp, RollForward, SumEquals, Exists, CoExists). **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. diff --git a/robosystems_client/api/extensions_robo_ledger/update_taxonomy_block.py b/robosystems_client/api/extensions_robo_ledger/update_taxonomy_block.py index 4f7f8f3..986cd55 100644 --- a/robosystems_client/api/extensions_robo_ledger/update_taxonomy_block.py +++ b/robosystems_client/api/extensions_robo_ledger/update_taxonomy_block.py @@ -115,7 +115,8 @@ def sync_detailed( Incrementally mutate a taxonomy block via typed delta lists (elements/structures/associations/rules to add, update, remove). Dispatches by the target taxonomy's stored `taxonomy_type`. Library-origin - block types (`reporting_standard`) surface 501. + block types (`reporting_standard`) surface 501. `reporting_extension` / `custom_ontology` authoring + may be disabled per environment (TAXONOMY_AUTHORING_ENABLED) — disabled surfaces 403. **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. @@ -163,7 +164,8 @@ def sync( Incrementally mutate a taxonomy block via typed delta lists (elements/structures/associations/rules to add, update, remove). Dispatches by the target taxonomy's stored `taxonomy_type`. Library-origin - block types (`reporting_standard`) surface 501. + block types (`reporting_standard`) surface 501. `reporting_extension` / `custom_ontology` authoring + may be disabled per environment (TAXONOMY_AUTHORING_ENABLED) — disabled surfaces 403. **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. @@ -206,7 +208,8 @@ async def asyncio_detailed( Incrementally mutate a taxonomy block via typed delta lists (elements/structures/associations/rules to add, update, remove). Dispatches by the target taxonomy's stored `taxonomy_type`. Library-origin - block types (`reporting_standard`) surface 501. + block types (`reporting_standard`) surface 501. `reporting_extension` / `custom_ontology` authoring + may be disabled per environment (TAXONOMY_AUTHORING_ENABLED) — disabled surfaces 403. **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. @@ -252,7 +255,8 @@ async def asyncio( Incrementally mutate a taxonomy block via typed delta lists (elements/structures/associations/rules to add, update, remove). Dispatches by the target taxonomy's stored `taxonomy_type`. Library-origin - block types (`reporting_standard`) surface 501. + block types (`reporting_standard`) surface 501. `reporting_extension` / `custom_ontology` authoring + may be disabled per environment (TAXONOMY_AUTHORING_ENABLED) — disabled surfaces 403. **Idempotency**: supply an `Idempotency-Key` header to make safe retries; replays within 24 hours return the same envelope. Reusing the key with a different body returns HTTP 409 Conflict. diff --git a/robosystems_client/models/__init__.py b/robosystems_client/models/__init__.py index 1f7c93d..35e9db6 100644 --- a/robosystems_client/models/__init__.py +++ b/robosystems_client/models/__init__.py @@ -35,6 +35,9 @@ from .change_reporting_style_response import ChangeReportingStyleResponse from .change_tier_op import ChangeTierOp from .change_tier_op_new_tier import ChangeTierOpNewTier +from .chart_lite import ChartLite +from .chart_panel_lite import ChartPanelLite +from .chart_series_lite import ChartSeriesLite from .checkout_response import CheckoutResponse from .checkout_status_response import CheckoutStatusResponse from .classification_lite import ClassificationLite @@ -43,6 +46,9 @@ from .close_period_response_rule_summary_type_0 import ( ClosePeriodResponseRuleSummaryType0, ) +from .compute_metrics_request import ComputeMetricsRequest +from .compute_metrics_response import ComputeMetricsResponse +from .computed_metric_lite import ComputedMetricLite from .connection_lite import ConnectionLite from .connection_options_response import ConnectionOptionsResponse from .connection_provider_info import ConnectionProviderInfo @@ -317,6 +323,12 @@ from .operation_envelope_close_period_response_status import ( OperationEnvelopeClosePeriodResponseStatus, ) +from .operation_envelope_compute_metrics_response import ( + OperationEnvelopeComputeMetricsResponse, +) +from .operation_envelope_compute_metrics_response_status import ( + OperationEnvelopeComputeMetricsResponseStatus, +) from .operation_envelope_delete_information_block_response import ( OperationEnvelopeDeleteInformationBlockResponse, ) @@ -594,6 +606,7 @@ from .share_report_operation import ShareReportOperation from .share_report_response import ShareReportResponse from .share_result_item import ShareResultItem +from .skipped_metric_lite import SkippedMetricLite from .sql_statement_request import SqlStatementRequest from .sql_statement_response import SqlStatementResponse from .sso_complete_request import SSOCompleteRequest @@ -605,6 +618,9 @@ from .storage_summary import StorageSummary from .structure_summary import StructureSummary from .structure_update_patch import StructureUpdatePatch +from .structure_update_patch_concept_arrangement_type_0 import ( + StructureUpdatePatchConceptArrangementType0, +) from .structure_update_patch_metadata_type_0 import StructureUpdatePatchMetadataType0 from .subgraph_quota_response import SubgraphQuotaResponse from .subgraph_response import SubgraphResponse @@ -763,12 +779,18 @@ "ChangeReportingStyleResponse", "ChangeTierOp", "ChangeTierOpNewTier", + "ChartLite", + "ChartPanelLite", + "ChartSeriesLite", "CheckoutResponse", "CheckoutStatusResponse", "ClassificationLite", "ClosePeriodOperation", "ClosePeriodResponse", "ClosePeriodResponseRuleSummaryType0", + "ComputedMetricLite", + "ComputeMetricsRequest", + "ComputeMetricsResponse", "ConnectionLite", "ConnectionOptionsResponse", "ConnectionProviderInfo", @@ -983,6 +1005,8 @@ "OperationEnvelopeChangeReportingStyleResponseStatus", "OperationEnvelopeClosePeriodResponse", "OperationEnvelopeClosePeriodResponseStatus", + "OperationEnvelopeComputeMetricsResponse", + "OperationEnvelopeComputeMetricsResponseStatus", "OperationEnvelopeDeleteInformationBlockResponse", "OperationEnvelopeDeleteInformationBlockResponseStatus", "OperationEnvelopeDeletePortfolioBlockResponse", @@ -1152,6 +1176,7 @@ "ShareReportOperation", "ShareReportResponse", "ShareResultItem", + "SkippedMetricLite", "SqlStatementRequest", "SqlStatementResponse", "SSOCompleteRequest", @@ -1163,6 +1188,7 @@ "StorageSummary", "StructureSummary", "StructureUpdatePatch", + "StructureUpdatePatchConceptArrangementType0", "StructureUpdatePatchMetadataType0", "SubgraphQuotaResponse", "SubgraphResponse", diff --git a/robosystems_client/models/chart_lite.py b/robosystems_client/models/chart_lite.py new file mode 100644 index 0000000..6f56946 --- /dev/null +++ b/robosystems_client/models/chart_lite.py @@ -0,0 +1,85 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.chart_panel_lite import ChartPanelLite + + +T = TypeVar("T", bound="ChartLite") + + +@_attrs_define +class ChartLite: + """Server-shaped chart projection — panel/series CONFIG, never values. + + The second real server-computed View arm (after ``rendering``). Values + come from ``rendering.rows`` joined by ``element_id``; the x-axis is + ``rendering.periods``. Renderers (report-components) turn one panel + into one chart. + + Attributes: + panels (list[ChartPanelLite] | Unset): + """ + + panels: list[ChartPanelLite] | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + panels: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.panels, Unset): + panels = [] + for panels_item_data in self.panels: + panels_item = panels_item_data.to_dict() + panels.append(panels_item) + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if panels is not UNSET: + field_dict["panels"] = panels + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.chart_panel_lite import ChartPanelLite + + d = dict(src_dict) + _panels = d.pop("panels", UNSET) + panels: list[ChartPanelLite] | Unset = UNSET + if _panels is not UNSET: + panels = [] + for panels_item_data in _panels: + panels_item = ChartPanelLite.from_dict(panels_item_data) + + panels.append(panels_item) + + chart_lite = cls( + panels=panels, + ) + + chart_lite.additional_properties = d + return chart_lite + + @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 diff --git a/robosystems_client/models/chart_panel_lite.py b/robosystems_client/models/chart_panel_lite.py new file mode 100644 index 0000000..5d21e35 --- /dev/null +++ b/robosystems_client/models/chart_panel_lite.py @@ -0,0 +1,135 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.chart_series_lite import ChartSeriesLite + + +T = TypeVar("T", bound="ChartPanelLite") + + +@_attrs_define +class ChartPanelLite: + """One chart panel — series sharing a y-axis format family. + + Mixed-unit catalogs are unplottable on one axis, so the server groups + rows into panels by ``item_type`` family (NULL falls back to + ``is_monetary``). The x-axis is always ``rendering.periods``. + + Attributes: + label (None | str | Unset): Panel heading — e.g. 'Monetary', 'Ratios'. + item_type (None | str | Unset): Format family shared by the panel's series (monetary | ratio | percent | + multiple | days); None for the untyped fallback panel. + kind (str | Unset): Per-panel mark — 'line' or 'bar'. Default: 'line'. + series (list[ChartSeriesLite] | Unset): + """ + + label: None | str | Unset = UNSET + item_type: None | str | Unset = UNSET + kind: str | Unset = "line" + series: list[ChartSeriesLite] | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + label: None | str | Unset + if isinstance(self.label, Unset): + label = UNSET + else: + label = self.label + + item_type: None | str | Unset + if isinstance(self.item_type, Unset): + item_type = UNSET + else: + item_type = self.item_type + + kind = self.kind + + series: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.series, Unset): + series = [] + for series_item_data in self.series: + series_item = series_item_data.to_dict() + series.append(series_item) + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if label is not UNSET: + field_dict["label"] = label + if item_type is not UNSET: + field_dict["item_type"] = item_type + if kind is not UNSET: + field_dict["kind"] = kind + if series is not UNSET: + field_dict["series"] = series + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.chart_series_lite import ChartSeriesLite + + d = dict(src_dict) + + def _parse_label(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + label = _parse_label(d.pop("label", UNSET)) + + def _parse_item_type(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + item_type = _parse_item_type(d.pop("item_type", UNSET)) + + kind = d.pop("kind", UNSET) + + _series = d.pop("series", UNSET) + series: list[ChartSeriesLite] | Unset = UNSET + if _series is not UNSET: + series = [] + for series_item_data in _series: + series_item = ChartSeriesLite.from_dict(series_item_data) + + series.append(series_item) + + chart_panel_lite = cls( + label=label, + item_type=item_type, + kind=kind, + series=series, + ) + + chart_panel_lite.additional_properties = d + return chart_panel_lite + + @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 diff --git a/robosystems_client/models/chart_series_lite.py b/robosystems_client/models/chart_series_lite.py new file mode 100644 index 0000000..f8f2164 --- /dev/null +++ b/robosystems_client/models/chart_series_lite.py @@ -0,0 +1,85 @@ +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="ChartSeriesLite") + + +@_attrs_define +class ChartSeriesLite: + """One plottable series in a chart panel. + + Carries structure and identity only — the values live in the sibling + ``rendering.rows`` (join on ``element_id``), so the chart arm never + duplicates the value matrix. ``key`` is the stable series identity for + client state (colors, toggles); today it equals ``element_id``, and + future axes (the forecast scenario) arrive as new fields on this + model, never a new arm shape. + + Attributes: + key (str): Stable series id — element_id today. + element_id (str): + label (str): Display name for legends. + """ + + key: str + element_id: str + label: str + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + key = self.key + + element_id = self.element_id + + label = self.label + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "key": key, + "element_id": element_id, + "label": label, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + key = d.pop("key") + + element_id = d.pop("element_id") + + label = d.pop("label") + + chart_series_lite = cls( + key=key, + element_id=element_id, + label=label, + ) + + chart_series_lite.additional_properties = d + return chart_series_lite + + @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 diff --git a/robosystems_client/models/compute_metrics_request.py b/robosystems_client/models/compute_metrics_request.py new file mode 100644 index 0000000..f73b59b --- /dev/null +++ b/robosystems_client/models/compute_metrics_request.py @@ -0,0 +1,133 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +from typing import Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ComputeMetricsRequest") + + +@_attrs_define +class ComputeMetricsRequest: + """Request body for the ``compute-metrics`` operation. + + Resolves the ``Derive`` rules scoped to the metric block, binds each + rule's operands to the entity's most recent persisted report facts at + ``period_end``, evaluates, and upserts the period's standing + ``factset_type='metric'`` FactSet (re-running a period replaces its + facts). One standing FactSet per (structure, entity, period_end) — the + accumulating time series. + + Attributes: + structure_id (str): Metric block structure (block_type='metric') to compute. + period_end (datetime.date): Period end to compute at. Operands bind to report facts whose period_end matches + exactly (instant balances as of this date; durations ending on it). + period_start (datetime.date | None | Unset): Optional lower bound for duration-operand binding and the standing + FactSet's period_start. + entity_id (None | str | Unset): Entity to compute for. Defaults to the graph's earliest-created entity (the + primary entity for single-entity graphs). + """ + + structure_id: str + period_end: datetime.date + period_start: datetime.date | None | Unset = UNSET + entity_id: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + structure_id = self.structure_id + + period_end = self.period_end.isoformat() + + period_start: None | str | Unset + if isinstance(self.period_start, Unset): + period_start = UNSET + elif isinstance(self.period_start, datetime.date): + period_start = self.period_start.isoformat() + else: + period_start = self.period_start + + entity_id: None | str | Unset + if isinstance(self.entity_id, Unset): + entity_id = UNSET + else: + entity_id = self.entity_id + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "structure_id": structure_id, + "period_end": period_end, + } + ) + if period_start is not UNSET: + field_dict["period_start"] = period_start + if entity_id is not UNSET: + field_dict["entity_id"] = entity_id + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + structure_id = d.pop("structure_id") + + period_end = datetime.date.fromisoformat(d.pop("period_end")) + + def _parse_period_start(data: object) -> datetime.date | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + period_start_type_0 = datetime.date.fromisoformat(data) + + return period_start_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.date | None | Unset, data) + + period_start = _parse_period_start(d.pop("period_start", UNSET)) + + def _parse_entity_id(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + entity_id = _parse_entity_id(d.pop("entity_id", UNSET)) + + compute_metrics_request = cls( + structure_id=structure_id, + period_end=period_end, + period_start=period_start, + entity_id=entity_id, + ) + + compute_metrics_request.additional_properties = d + return compute_metrics_request + + @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 diff --git a/robosystems_client/models/compute_metrics_response.py b/robosystems_client/models/compute_metrics_response.py new file mode 100644 index 0000000..aef73db --- /dev/null +++ b/robosystems_client/models/compute_metrics_response.py @@ -0,0 +1,152 @@ +from __future__ import annotations + +import datetime +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.computed_metric_lite import ComputedMetricLite + from ..models.skipped_metric_lite import SkippedMetricLite + + +T = TypeVar("T", bound="ComputeMetricsResponse") + + +@_attrs_define +class ComputeMetricsResponse: + """Response for the ``compute-metrics`` operation. + + Attributes: + structure_id (str): + entity_id (str): + period_end (datetime.date): + fact_set_id (None | str | Unset): Standing metric FactSet for the period — None when every metric was skipped + and no prior set existed. + computed (list[ComputedMetricLite] | Unset): + skipped (list[SkippedMetricLite] | Unset): + """ + + structure_id: str + entity_id: str + period_end: datetime.date + fact_set_id: None | str | Unset = UNSET + computed: list[ComputedMetricLite] | Unset = UNSET + skipped: list[SkippedMetricLite] | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + structure_id = self.structure_id + + entity_id = self.entity_id + + period_end = self.period_end.isoformat() + + fact_set_id: None | str | Unset + if isinstance(self.fact_set_id, Unset): + fact_set_id = UNSET + else: + fact_set_id = self.fact_set_id + + computed: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.computed, Unset): + computed = [] + for computed_item_data in self.computed: + computed_item = computed_item_data.to_dict() + computed.append(computed_item) + + skipped: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.skipped, Unset): + skipped = [] + for skipped_item_data in self.skipped: + skipped_item = skipped_item_data.to_dict() + skipped.append(skipped_item) + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "structure_id": structure_id, + "entity_id": entity_id, + "period_end": period_end, + } + ) + if fact_set_id is not UNSET: + field_dict["fact_set_id"] = fact_set_id + if computed is not UNSET: + field_dict["computed"] = computed + if skipped is not UNSET: + field_dict["skipped"] = skipped + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.computed_metric_lite import ComputedMetricLite + from ..models.skipped_metric_lite import SkippedMetricLite + + d = dict(src_dict) + structure_id = d.pop("structure_id") + + entity_id = d.pop("entity_id") + + period_end = datetime.date.fromisoformat(d.pop("period_end")) + + def _parse_fact_set_id(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + fact_set_id = _parse_fact_set_id(d.pop("fact_set_id", UNSET)) + + _computed = d.pop("computed", UNSET) + computed: list[ComputedMetricLite] | Unset = UNSET + if _computed is not UNSET: + computed = [] + for computed_item_data in _computed: + computed_item = ComputedMetricLite.from_dict(computed_item_data) + + computed.append(computed_item) + + _skipped = d.pop("skipped", UNSET) + skipped: list[SkippedMetricLite] | Unset = UNSET + if _skipped is not UNSET: + skipped = [] + for skipped_item_data in _skipped: + skipped_item = SkippedMetricLite.from_dict(skipped_item_data) + + skipped.append(skipped_item) + + compute_metrics_response = cls( + structure_id=structure_id, + entity_id=entity_id, + period_end=period_end, + fact_set_id=fact_set_id, + computed=computed, + skipped=skipped, + ) + + compute_metrics_response.additional_properties = d + return compute_metrics_response + + @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 diff --git a/robosystems_client/models/computed_metric_lite.py b/robosystems_client/models/computed_metric_lite.py new file mode 100644 index 0000000..0d836b0 --- /dev/null +++ b/robosystems_client/models/computed_metric_lite.py @@ -0,0 +1,145 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ComputedMetricLite") + + +@_attrs_define +class ComputedMetricLite: + """One metric computed by a ``compute-metrics`` run. + + Attributes: + rule_id (str): Derive rule that produced the value. + element_id (str): Metric element the fact was written for. + name (str): Metric display name. + value (float): Computed value. + unit (str): Fact unit — 'USD' for monetary, 'days' for days, else 'pure'. + period_type (str): 'instant' or 'duration'. + element_qname (None | str | Unset): Metric element qname (e.g. rs-metric:CurrentRatio). + item_type (None | str | Unset): Format family from the metric element (monetary | ratio | percent | multiple | + days). None means untyped; fall back to unit. + """ + + rule_id: str + element_id: str + name: str + value: float + unit: str + period_type: str + element_qname: None | str | Unset = UNSET + item_type: None | str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + rule_id = self.rule_id + + element_id = self.element_id + + name = self.name + + value = self.value + + unit = self.unit + + period_type = self.period_type + + element_qname: None | str | Unset + if isinstance(self.element_qname, Unset): + element_qname = UNSET + else: + element_qname = self.element_qname + + item_type: None | str | Unset + if isinstance(self.item_type, Unset): + item_type = UNSET + else: + item_type = self.item_type + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "rule_id": rule_id, + "element_id": element_id, + "name": name, + "value": value, + "unit": unit, + "period_type": period_type, + } + ) + if element_qname is not UNSET: + field_dict["element_qname"] = element_qname + if item_type is not UNSET: + field_dict["item_type"] = item_type + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + rule_id = d.pop("rule_id") + + element_id = d.pop("element_id") + + name = d.pop("name") + + value = d.pop("value") + + unit = d.pop("unit") + + period_type = d.pop("period_type") + + def _parse_element_qname(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + element_qname = _parse_element_qname(d.pop("element_qname", UNSET)) + + def _parse_item_type(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + item_type = _parse_item_type(d.pop("item_type", UNSET)) + + computed_metric_lite = cls( + rule_id=rule_id, + element_id=element_id, + name=name, + value=value, + unit=unit, + period_type=period_type, + element_qname=element_qname, + item_type=item_type, + ) + + computed_metric_lite.additional_properties = d + return computed_metric_lite + + @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 diff --git a/robosystems_client/models/element_lite.py b/robosystems_client/models/element_lite.py index 28de549..04ebe9e 100644 --- a/robosystems_client/models/element_lite.py +++ b/robosystems_client/models/element_lite.py @@ -30,6 +30,8 @@ class ElementLite: is_monetary (bool | Unset): Default: True. balance_type (None | str | Unset): period_type (None | str | Unset): + item_type (None | str | Unset): Value-domain vocabulary (monetary | ratio | percent | multiple | days | string | + …). None means untyped; fall back to is_monetary. """ id: str @@ -41,6 +43,7 @@ class ElementLite: is_monetary: bool | Unset = True balance_type: None | str | Unset = UNSET period_type: None | str | Unset = UNSET + item_type: None | str | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: @@ -78,6 +81,12 @@ def to_dict(self) -> dict[str, Any]: else: period_type = self.period_type + item_type: None | str | Unset + if isinstance(self.item_type, Unset): + item_type = UNSET + else: + item_type = self.item_type + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -99,6 +108,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["balance_type"] = balance_type if period_type is not UNSET: field_dict["period_type"] = period_type + if item_type is not UNSET: + field_dict["item_type"] = item_type return field_dict @@ -151,6 +162,15 @@ def _parse_period_type(data: object) -> None | str | Unset: period_type = _parse_period_type(d.pop("period_type", UNSET)) + def _parse_item_type(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + item_type = _parse_item_type(d.pop("item_type", UNSET)) + element_lite = cls( id=id, name=name, @@ -161,6 +181,7 @@ def _parse_period_type(data: object) -> None | str | Unset: is_monetary=is_monetary, balance_type=balance_type, period_type=period_type, + item_type=item_type, ) element_lite.additional_properties = d diff --git a/robosystems_client/models/information_block_envelope.py b/robosystems_client/models/information_block_envelope.py index b00e6d0..5da074f 100644 --- a/robosystems_client/models/information_block_envelope.py +++ b/robosystems_client/models/information_block_envelope.py @@ -74,7 +74,9 @@ class InformationBlockEnvelope: mode; missing projections (those still in backlog) render as empty states without breaking the dispatcher. - Today: ``rendering`` is computed for the statement family. + Today: ``rendering`` is computed for the statement family, and + ``chart`` (the 7th arm — panel/series config over the rendering's + rows and periods) for metric blocks. Other arms (``fact_table``, ``model_structure``, ``verification_results``, ``report_elements``, ``business_rules``) come online as their backend support lands; ``fact_table`` is trivially derivable from diff --git a/robosystems_client/models/operation_envelope_compute_metrics_response.py b/robosystems_client/models/operation_envelope_compute_metrics_response.py new file mode 100644 index 0000000..08f0563 --- /dev/null +++ b/robosystems_client/models/operation_envelope_compute_metrics_response.py @@ -0,0 +1,158 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..models.operation_envelope_compute_metrics_response_status import ( + OperationEnvelopeComputeMetricsResponseStatus, +) +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.compute_metrics_response import ComputeMetricsResponse + + +T = TypeVar("T", bound="OperationEnvelopeComputeMetricsResponse") + + +@_attrs_define +class OperationEnvelopeComputeMetricsResponse: + """ + Attributes: + operation (str): Kebab-case operation name + operation_id (str): op_-prefixed ULID for audit and SSE correlation + status (OperationEnvelopeComputeMetricsResponseStatus): Operation lifecycle state + at (str): ISO-8601 UTC timestamp + result (ComputeMetricsResponse | None | Unset): Command-specific result payload + created_by (None | str | Unset): User ID that initiated the operation (null for legacy callers) + idempotent_replay (bool | Unset): True when this envelope came from the idempotency cache — the underlying + command did not execute again. False on fresh executions. Default: False. + """ + + operation: str + operation_id: str + status: OperationEnvelopeComputeMetricsResponseStatus + at: str + result: ComputeMetricsResponse | None | Unset = UNSET + created_by: None | str | Unset = UNSET + idempotent_replay: bool | Unset = False + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + from ..models.compute_metrics_response import ComputeMetricsResponse + + operation = self.operation + + operation_id = self.operation_id + + status = self.status.value + + at = self.at + + result: dict[str, Any] | None | Unset + if isinstance(self.result, Unset): + result = UNSET + elif isinstance(self.result, ComputeMetricsResponse): + result = self.result.to_dict() + else: + result = self.result + + created_by: None | str | Unset + if isinstance(self.created_by, Unset): + created_by = UNSET + else: + created_by = self.created_by + + idempotent_replay = self.idempotent_replay + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "operation": operation, + "operationId": operation_id, + "status": status, + "at": at, + } + ) + if result is not UNSET: + field_dict["result"] = result + if created_by is not UNSET: + field_dict["createdBy"] = created_by + if idempotent_replay is not UNSET: + field_dict["idempotentReplay"] = idempotent_replay + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.compute_metrics_response import ComputeMetricsResponse + + d = dict(src_dict) + operation = d.pop("operation") + + operation_id = d.pop("operationId") + + status = OperationEnvelopeComputeMetricsResponseStatus(d.pop("status")) + + at = d.pop("at") + + def _parse_result(data: object) -> ComputeMetricsResponse | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + result_type_0 = ComputeMetricsResponse.from_dict(data) + + return result_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(ComputeMetricsResponse | None | Unset, data) + + result = _parse_result(d.pop("result", UNSET)) + + def _parse_created_by(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + created_by = _parse_created_by(d.pop("createdBy", UNSET)) + + idempotent_replay = d.pop("idempotentReplay", UNSET) + + operation_envelope_compute_metrics_response = cls( + operation=operation, + operation_id=operation_id, + status=status, + at=at, + result=result, + created_by=created_by, + idempotent_replay=idempotent_replay, + ) + + operation_envelope_compute_metrics_response.additional_properties = d + return operation_envelope_compute_metrics_response + + @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 diff --git a/robosystems_client/models/operation_envelope_compute_metrics_response_status.py b/robosystems_client/models/operation_envelope_compute_metrics_response_status.py new file mode 100644 index 0000000..39b6668 --- /dev/null +++ b/robosystems_client/models/operation_envelope_compute_metrics_response_status.py @@ -0,0 +1,10 @@ +from enum import Enum + + +class OperationEnvelopeComputeMetricsResponseStatus(str, Enum): + COMPLETED = "completed" + FAILED = "failed" + PENDING = "pending" + + def __str__(self) -> str: + return str(self.value) diff --git a/robosystems_client/models/rendering_row_lite.py b/robosystems_client/models/rendering_row_lite.py index 54568ad..abf2869 100644 --- a/robosystems_client/models/rendering_row_lite.py +++ b/robosystems_client/models/rendering_row_lite.py @@ -29,6 +29,8 @@ class RenderingRowLite: 'equity', 'revenue', 'expense'. Surfaced so the viewer can color-code or group rows without a follow-up trait lookup. balance_type (None | str | Unset): + item_type (None | str | Unset): Value-domain format family from the element (monetary | ratio | percent | + multiple | days | …). Drives per-row value formatting; None falls back to is_monetary on the element. values (list[float | None] | Unset): text_value (None | str | Unset): Narrative payload for text-block disclosure rows (markdown); numeric rows carry values instead. @@ -41,6 +43,7 @@ class RenderingRowLite: element_qname: None | str | Unset = UNSET classification: None | str | Unset = UNSET balance_type: None | str | Unset = UNSET + item_type: None | str | Unset = UNSET values: list[float | None] | Unset = UNSET text_value: None | str | Unset = UNSET is_subtotal: bool | Unset = False @@ -70,6 +73,12 @@ def to_dict(self) -> dict[str, Any]: else: balance_type = self.balance_type + item_type: None | str | Unset + if isinstance(self.item_type, Unset): + item_type = UNSET + else: + item_type = self.item_type + values: list[float | None] | Unset = UNSET if not isinstance(self.values, Unset): values = [] @@ -102,6 +111,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["classification"] = classification if balance_type is not UNSET: field_dict["balance_type"] = balance_type + if item_type is not UNSET: + field_dict["item_type"] = item_type if values is not UNSET: field_dict["values"] = values if text_value is not UNSET: @@ -147,6 +158,15 @@ def _parse_balance_type(data: object) -> None | str | Unset: balance_type = _parse_balance_type(d.pop("balance_type", UNSET)) + def _parse_item_type(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + item_type = _parse_item_type(d.pop("item_type", UNSET)) + _values = d.pop("values", UNSET) values: list[float | None] | Unset = UNSET if _values is not UNSET: @@ -181,6 +201,7 @@ def _parse_text_value(data: object) -> None | str | Unset: element_qname=element_qname, classification=classification, balance_type=balance_type, + item_type=item_type, values=values, text_value=text_value, is_subtotal=is_subtotal, diff --git a/robosystems_client/models/skipped_metric_lite.py b/robosystems_client/models/skipped_metric_lite.py new file mode 100644 index 0000000..f38348b --- /dev/null +++ b/robosystems_client/models/skipped_metric_lite.py @@ -0,0 +1,107 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="SkippedMetricLite") + + +@_attrs_define +class SkippedMetricLite: + """One metric a ``compute-metrics`` run could not compute. + + Soft-fail by design: a missing operand fact (e.g. InterestExpense for a + debt-free entity) or an undefined ratio (division by zero) skips the + metric with a reason — it never errors the run. + + Attributes: + rule_id (str): Derive rule that was skipped. + reason (str): Why the metric was skipped. + element_qname (None | str | Unset): Metric element qname the rule targets. + missing (list[str] | Unset): Operand qnames with no bound fact at the period, when applicable. + """ + + rule_id: str + reason: str + element_qname: None | str | Unset = UNSET + missing: list[str] | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + rule_id = self.rule_id + + reason = self.reason + + element_qname: None | str | Unset + if isinstance(self.element_qname, Unset): + element_qname = UNSET + else: + element_qname = self.element_qname + + missing: list[str] | Unset = UNSET + if not isinstance(self.missing, Unset): + missing = self.missing + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "rule_id": rule_id, + "reason": reason, + } + ) + if element_qname is not UNSET: + field_dict["element_qname"] = element_qname + if missing is not UNSET: + field_dict["missing"] = missing + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + rule_id = d.pop("rule_id") + + reason = d.pop("reason") + + def _parse_element_qname(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + element_qname = _parse_element_qname(d.pop("element_qname", UNSET)) + + missing = cast(list[str], d.pop("missing", UNSET)) + + skipped_metric_lite = cls( + rule_id=rule_id, + reason=reason, + element_qname=element_qname, + missing=missing, + ) + + skipped_metric_lite.additional_properties = d + return skipped_metric_lite + + @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 diff --git a/robosystems_client/models/structure_update_patch.py b/robosystems_client/models/structure_update_patch.py index 4d29df7..535489a 100644 --- a/robosystems_client/models/structure_update_patch.py +++ b/robosystems_client/models/structure_update_patch.py @@ -6,6 +6,9 @@ from attrs import define as _attrs_define from attrs import field as _attrs_field +from ..models.structure_update_patch_concept_arrangement_type_0 import ( + StructureUpdatePatchConceptArrangementType0, +) from ..types import UNSET, Unset if TYPE_CHECKING: @@ -21,18 +24,27 @@ class StructureUpdatePatch: """Partial-update patch for a single structure, keyed by structure_id. - Attributes: - structure_id (str): Structure id to update. - name (None | str | Unset): - description (None | str | Unset): - role_uri (None | str | Unset): - metadata (None | StructureUpdatePatchMetadataType0 | Unset): + ``concept_arrangement`` makes a mis-CAP'd structure repairable in + place (e.g. promoting a ``set`` note to ``roll_up`` so it gains a + footing rule); ``block_type`` stays immutable — it drives block-type + routing, so changing it is a re-create, not an edit. + + Attributes: + structure_id (str): Structure id to update. + name (None | str | Unset): + description (None | str | Unset): + role_uri (None | str | Unset): + concept_arrangement (None | StructureUpdatePatchConceptArrangementType0 | Unset): + metadata (None | StructureUpdatePatchMetadataType0 | Unset): """ structure_id: str name: None | str | Unset = UNSET description: None | str | Unset = UNSET role_uri: None | str | Unset = UNSET + concept_arrangement: None | StructureUpdatePatchConceptArrangementType0 | Unset = ( + UNSET + ) metadata: None | StructureUpdatePatchMetadataType0 | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -61,6 +73,16 @@ def to_dict(self) -> dict[str, Any]: else: role_uri = self.role_uri + concept_arrangement: None | str | Unset + if isinstance(self.concept_arrangement, Unset): + concept_arrangement = UNSET + elif isinstance( + self.concept_arrangement, StructureUpdatePatchConceptArrangementType0 + ): + concept_arrangement = self.concept_arrangement.value + else: + concept_arrangement = self.concept_arrangement + metadata: dict[str, Any] | None | Unset if isinstance(self.metadata, Unset): metadata = UNSET @@ -82,6 +104,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["description"] = description if role_uri is not UNSET: field_dict["role_uri"] = role_uri + if concept_arrangement is not UNSET: + field_dict["concept_arrangement"] = concept_arrangement if metadata is not UNSET: field_dict["metadata"] = metadata @@ -123,6 +147,27 @@ def _parse_role_uri(data: object) -> None | str | Unset: role_uri = _parse_role_uri(d.pop("role_uri", UNSET)) + def _parse_concept_arrangement( + data: object, + ) -> None | StructureUpdatePatchConceptArrangementType0 | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + concept_arrangement_type_0 = StructureUpdatePatchConceptArrangementType0(data) + + return concept_arrangement_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(None | StructureUpdatePatchConceptArrangementType0 | Unset, data) + + concept_arrangement = _parse_concept_arrangement( + d.pop("concept_arrangement", UNSET) + ) + def _parse_metadata( data: object, ) -> None | StructureUpdatePatchMetadataType0 | Unset: @@ -147,6 +192,7 @@ def _parse_metadata( name=name, description=description, role_uri=role_uri, + concept_arrangement=concept_arrangement, metadata=metadata, ) diff --git a/robosystems_client/models/structure_update_patch_concept_arrangement_type_0.py b/robosystems_client/models/structure_update_patch_concept_arrangement_type_0.py new file mode 100644 index 0000000..d9ccce1 --- /dev/null +++ b/robosystems_client/models/structure_update_patch_concept_arrangement_type_0.py @@ -0,0 +1,22 @@ +from enum import Enum + + +class StructureUpdatePatchConceptArrangementType0(str, Enum): + ADJUSTMENT = "adjustment" + ARITHMETIC = "arithmetic" + COMPOUND_FACT = "compound_fact" + GRID = "grid" + LEVEL1_TEXTBLOCK = "level1_textblock" + LEVEL2_TEXTBLOCK = "level2_textblock" + LEVEL3_TEXTBLOCK = "level3_textblock" + LEVEL4_DETAIL = "level4_detail" + ROLL_FORWARD = "roll_forward" + ROLL_FORWARD_INFO = "roll_forward_info" + ROLL_UP = "roll_up" + SET = "set" + TABLE_EQUIVALENT_TEXTBLOCK = "table_equivalent_textblock" + TEXT_BLOCK = "text_block" + VARIANCE = "variance" + + def __str__(self) -> str: + return str(self.value) diff --git a/robosystems_client/models/taxonomy_block_rule_request.py b/robosystems_client/models/taxonomy_block_rule_request.py index a2f63ab..0d1bc65 100644 --- a/robosystems_client/models/taxonomy_block_rule_request.py +++ b/robosystems_client/models/taxonomy_block_rule_request.py @@ -48,7 +48,9 @@ class TaxonomyBlockRuleRequest: Attributes: name (str): Rule identifier, unique within envelope. rule_category (TaxonomyBlockRuleRequestRuleCategory): One of 8 cm:VerificationRule subclasses. - rule_pattern (TaxonomyBlockRuleRequestRulePattern): One of 11 cm:BusinessRulePattern mechanisms. + rule_pattern (TaxonomyBlockRuleRequestRulePattern): One of the cm:BusinessRulePattern mechanisms. 'Derive' rules + COMPUTE a value from bound operand facts (compute-metrics) rather than verify one — the tenant-authored-metric + pattern. expression (str): XPath-flavored predicate body (the rule expression). description (None | str | Unset): variables (list[TaxonomyBlockRuleRequestVariablesItem] | Unset): ``$Variable`` → qname bindings. Each entry is diff --git a/robosystems_client/models/taxonomy_block_rule_request_rule_pattern.py b/robosystems_client/models/taxonomy_block_rule_request_rule_pattern.py index 6a131c8..7026af7 100644 --- a/robosystems_client/models/taxonomy_block_rule_request_rule_pattern.py +++ b/robosystems_client/models/taxonomy_block_rule_request_rule_pattern.py @@ -4,6 +4,7 @@ class TaxonomyBlockRuleRequestRulePattern(str, Enum): ADJUSTMENT = "Adjustment" COEXISTS = "CoExists" + DERIVE = "Derive" EQUALTO = "EqualTo" EXISTS = "Exists" GREATERTHAN = "GreaterThan" diff --git a/robosystems_client/models/view_projections.py b/robosystems_client/models/view_projections.py index 3404938..70483f2 100644 --- a/robosystems_client/models/view_projections.py +++ b/robosystems_client/models/view_projections.py @@ -9,6 +9,7 @@ from ..types import UNSET, Unset if TYPE_CHECKING: + from ..models.chart_lite import ChartLite from ..models.rendering_lite import RenderingLite @@ -25,7 +26,9 @@ class ViewProjections: mode; missing projections (those still in backlog) render as empty states without breaking the dispatcher. - Today: ``rendering`` is computed for the statement family. + Today: ``rendering`` is computed for the statement family, and + ``chart`` (the 7th arm — panel/series config over the rendering's + rows and periods) for metric blocks. Other arms (``fact_table``, ``model_structure``, ``verification_results``, ``report_elements``, ``business_rules``) come online as their backend support lands; ``fact_table`` is trivially derivable from @@ -34,12 +37,15 @@ class ViewProjections: Attributes: rendering (None | RenderingLite | Unset): + chart (ChartLite | None | Unset): """ rendering: None | RenderingLite | Unset = UNSET + chart: ChartLite | None | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: + from ..models.chart_lite import ChartLite from ..models.rendering_lite import RenderingLite rendering: dict[str, Any] | None | Unset @@ -50,16 +56,27 @@ def to_dict(self) -> dict[str, Any]: else: rendering = self.rendering + chart: dict[str, Any] | None | Unset + if isinstance(self.chart, Unset): + chart = UNSET + elif isinstance(self.chart, ChartLite): + chart = self.chart.to_dict() + else: + chart = self.chart + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update({}) if rendering is not UNSET: field_dict["rendering"] = rendering + if chart is not UNSET: + field_dict["chart"] = chart return field_dict @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.chart_lite import ChartLite from ..models.rendering_lite import RenderingLite d = dict(src_dict) @@ -81,8 +98,26 @@ def _parse_rendering(data: object) -> None | RenderingLite | Unset: rendering = _parse_rendering(d.pop("rendering", UNSET)) + def _parse_chart(data: object) -> ChartLite | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + chart_type_0 = ChartLite.from_dict(data) + + return chart_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(ChartLite | None | Unset, data) + + chart = _parse_chart(d.pop("chart", UNSET)) + view_projections = cls( rendering=rendering, + chart=chart, ) view_projections.additional_properties = d