diff --git a/robosystems_client/api/connections/create_connection.py b/robosystems_client/api/connections/create_connection.py index a53979c..c13bec5 100644 --- a/robosystems_client/api/connections/create_connection.py +++ b/robosystems_client/api/connections/create_connection.py @@ -107,10 +107,9 @@ def sync_detailed( ) -> Response[Any | ConnectionResponse | ErrorResponse | HTTPValidationError]: """Create Connection - SEC: provide entity CIK, no auth needed. QuickBooks: returns an OAuth URL — complete the flow to - activate. External: registers a source namespace for an integration that writes through the public - API. One connection allowed per provider per graph, except 'external' which allows one per - source_name. + QuickBooks: returns an OAuth URL — complete the flow to activate. External: registers a source + namespace for an integration that writes through the public API. One connection allowed per provider + per graph, except 'external' which allows one per source_name. Args: graph_id (str): @@ -144,10 +143,9 @@ def sync( ) -> Any | ConnectionResponse | ErrorResponse | HTTPValidationError | None: """Create Connection - SEC: provide entity CIK, no auth needed. QuickBooks: returns an OAuth URL — complete the flow to - activate. External: registers a source namespace for an integration that writes through the public - API. One connection allowed per provider per graph, except 'external' which allows one per - source_name. + QuickBooks: returns an OAuth URL — complete the flow to activate. External: registers a source + namespace for an integration that writes through the public API. One connection allowed per provider + per graph, except 'external' which allows one per source_name. Args: graph_id (str): @@ -176,10 +174,9 @@ async def asyncio_detailed( ) -> Response[Any | ConnectionResponse | ErrorResponse | HTTPValidationError]: """Create Connection - SEC: provide entity CIK, no auth needed. QuickBooks: returns an OAuth URL — complete the flow to - activate. External: registers a source namespace for an integration that writes through the public - API. One connection allowed per provider per graph, except 'external' which allows one per - source_name. + QuickBooks: returns an OAuth URL — complete the flow to activate. External: registers a source + namespace for an integration that writes through the public API. One connection allowed per provider + per graph, except 'external' which allows one per source_name. Args: graph_id (str): @@ -211,10 +208,9 @@ async def asyncio( ) -> Any | ConnectionResponse | ErrorResponse | HTTPValidationError | None: """Create Connection - SEC: provide entity CIK, no auth needed. QuickBooks: returns an OAuth URL — complete the flow to - activate. External: registers a source namespace for an integration that writes through the public - API. One connection allowed per provider per graph, except 'external' which allows one per - source_name. + QuickBooks: returns an OAuth URL — complete the flow to activate. External: registers a source + namespace for an integration that writes through the public API. One connection allowed per provider + per graph, except 'external' which allows one per source_name. Args: graph_id (str): diff --git a/robosystems_client/api/connections/get_connection_options.py b/robosystems_client/api/connections/get_connection_options.py index 834176a..dd85933 100644 --- a/robosystems_client/api/connections/get_connection_options.py +++ b/robosystems_client/api/connections/get_connection_options.py @@ -94,7 +94,7 @@ def sync_detailed( """List Connection Options Returns available providers and their requirements. Only enabled providers are included (gated by - feature flags). SEC requires no auth; QuickBooks requires OAuth 2.0. + feature flags). QuickBooks requires OAuth 2.0; external connections require no auth. Args: graph_id (str): @@ -126,7 +126,7 @@ def sync( """List Connection Options Returns available providers and their requirements. Only enabled providers are included (gated by - feature flags). SEC requires no auth; QuickBooks requires OAuth 2.0. + feature flags). QuickBooks requires OAuth 2.0; external connections require no auth. Args: graph_id (str): @@ -153,7 +153,7 @@ async def asyncio_detailed( """List Connection Options Returns available providers and their requirements. Only enabled providers are included (gated by - feature flags). SEC requires no auth; QuickBooks requires OAuth 2.0. + feature flags). QuickBooks requires OAuth 2.0; external connections require no auth. Args: graph_id (str): @@ -183,7 +183,7 @@ async def asyncio( """List Connection Options Returns available providers and their requirements. Only enabled providers are included (gated by - feature flags). SEC requires no auth; QuickBooks requires OAuth 2.0. + feature flags). QuickBooks requires OAuth 2.0; external connections require no auth. Args: graph_id (str): diff --git a/robosystems_client/api/connections/sync_connection.py b/robosystems_client/api/connections/sync_connection.py index b85c6e7..3e0c2fe 100644 --- a/robosystems_client/api/connections/sync_connection.py +++ b/robosystems_client/api/connections/sync_connection.py @@ -118,9 +118,11 @@ def sync_detailed( ) -> Response[Any | ErrorResponse | OperationEnvelope]: """Sync Connection - SEC: downloads latest EDGAR filings (5-10 min). QuickBooks: fetches transactions, balances, and - chart of accounts. Async — returns an `OperationEnvelope` with the provider task id; completion is - reflected in the connection's `last_sync` timestamp. Supports `Idempotency-Key`. + QuickBooks: fetches transactions, balances, and chart of accounts; the envelope is `pending` with + the run's `task_id`, and completion is reflected in the connection's `last_sync` timestamp. External + connections are push-based and have nothing to pull; the envelope is `completed` with a null + `task_id` and a message saying so — there is nothing to poll. Returns an `OperationEnvelope`; + supports `Idempotency-Key`. Args: graph_id (str): @@ -160,9 +162,11 @@ def sync( ) -> Any | ErrorResponse | OperationEnvelope | None: """Sync Connection - SEC: downloads latest EDGAR filings (5-10 min). QuickBooks: fetches transactions, balances, and - chart of accounts. Async — returns an `OperationEnvelope` with the provider task id; completion is - reflected in the connection's `last_sync` timestamp. Supports `Idempotency-Key`. + QuickBooks: fetches transactions, balances, and chart of accounts; the envelope is `pending` with + the run's `task_id`, and completion is reflected in the connection's `last_sync` timestamp. External + connections are push-based and have nothing to pull; the envelope is `completed` with a null + `task_id` and a message saying so — there is nothing to poll. Returns an `OperationEnvelope`; + supports `Idempotency-Key`. Args: graph_id (str): @@ -197,9 +201,11 @@ async def asyncio_detailed( ) -> Response[Any | ErrorResponse | OperationEnvelope]: """Sync Connection - SEC: downloads latest EDGAR filings (5-10 min). QuickBooks: fetches transactions, balances, and - chart of accounts. Async — returns an `OperationEnvelope` with the provider task id; completion is - reflected in the connection's `last_sync` timestamp. Supports `Idempotency-Key`. + QuickBooks: fetches transactions, balances, and chart of accounts; the envelope is `pending` with + the run's `task_id`, and completion is reflected in the connection's `last_sync` timestamp. External + connections are push-based and have nothing to pull; the envelope is `completed` with a null + `task_id` and a message saying so — there is nothing to poll. Returns an `OperationEnvelope`; + supports `Idempotency-Key`. Args: graph_id (str): @@ -237,9 +243,11 @@ async def asyncio( ) -> Any | ErrorResponse | OperationEnvelope | None: """Sync Connection - SEC: downloads latest EDGAR filings (5-10 min). QuickBooks: fetches transactions, balances, and - chart of accounts. Async — returns an `OperationEnvelope` with the provider task id; completion is - reflected in the connection's `last_sync` timestamp. Supports `Idempotency-Key`. + QuickBooks: fetches transactions, balances, and chart of accounts; the envelope is `pending` with + the run's `task_id`, and completion is reflected in the connection's `last_sync` timestamp. External + connections are push-based and have nothing to pull; the envelope is `completed` with a null + `task_id` and a message saying so — there is nothing to poll. Returns an `OperationEnvelope`; + supports `Idempotency-Key`. Args: graph_id (str): 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 b087971..7af6b7a 100644 --- a/robosystems_client/api/extensions_robo_ledger/create_taxonomy_block.py +++ b/robosystems_client/api/extensions_robo_ledger/create_taxonomy_block.py @@ -137,8 +137,7 @@ def sync_detailed( extends a library taxonomy) and ignored otherwise. The library path (seeding ``reporting_standard`` rows) does NOT flow - through this envelope — it uses a dedicated library writer that bypasses - these caps and tenant scoping. + through this envelope; library content is not tenant-writable here. Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. @@ -194,8 +193,7 @@ def sync( extends a library taxonomy) and ignored otherwise. The library path (seeding ``reporting_standard`` rows) does NOT flow - through this envelope — it uses a dedicated library writer that bypasses - these caps and tenant scoping. + through this envelope; library content is not tenant-writable here. Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. @@ -246,8 +244,7 @@ async def asyncio_detailed( extends a library taxonomy) and ignored otherwise. The library path (seeding ``reporting_standard`` rows) does NOT flow - through this envelope — it uses a dedicated library writer that bypasses - these caps and tenant scoping. + through this envelope; library content is not tenant-writable here. Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. @@ -301,8 +298,7 @@ async def asyncio( extends a library taxonomy) and ignored otherwise. The library path (seeding ``reporting_standard`` rows) does NOT flow - through this envelope — it uses a dedicated library writer that bypasses - these caps and tenant scoping. + through this envelope; library content is not tenant-writable here. Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. diff --git a/robosystems_client/api/extensions_robo_ledger/terminate_schedule.py b/robosystems_client/api/extensions_robo_ledger/terminate_schedule.py new file mode 100644 index 0000000..5fcd300 --- /dev/null +++ b/robosystems_client/api/extensions_robo_ledger/terminate_schedule.py @@ -0,0 +1,342 @@ +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.error_response import ErrorResponse +from ...models.operation_envelope_terminate_schedule_response import ( + OperationEnvelopeTerminateScheduleResponse, +) +from ...models.terminate_schedule_request import TerminateScheduleRequest +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + graph_id: str, + *, + body: TerminateScheduleRequest, + 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/terminate-schedule".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 | OperationEnvelopeTerminateScheduleResponse | None: + if response.status_code == 200: + response_200 = OperationEnvelopeTerminateScheduleResponse.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 | OperationEnvelopeTerminateScheduleResponse]: + 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: TerminateScheduleRequest, + idempotency_key: None | str | Unset = UNSET, +) -> Response[ErrorResponse | OperationEnvelopeTerminateScheduleResponse]: + """Terminate Schedule Early (No Entry) + + End a schedule early at a month-end cutoff without booking any entry. In one transaction: deletes + forward facts past the cutoff (refusing when posted entries exist past it; stale drafts past it are + deleted), voids the remaining obligation chain past the cutoff (pending and classified rows), and + rewrites the SumEquals rule to prove the truncated curve. History at or before the cutoff is + untouched, so open months the schedule still covers close normally. Use this when the termination's + GL effect is already booked (an asset transferred via a manual entry, a prepaid refunded in the + source system) or none is wanted; when the derecognition entry still needs to be booked, use create- + event-block(event_type='asset_disposed') instead — the disposal handler posts it atomically with the + same obligation void. Run BEFORE promote-obligations at close so terminated periods are never + drafted. + + **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 (TerminateScheduleRequest): End a schedule early at a month-end cutoff — no entry is + booked. + + The no-entry half of schedule retirement, for terminations whose GL + effect is already booked (an asset transferred via a manual journal + entry, a prepaid refunded in the source system) or where none is + wanted. In one transaction: deletes forward facts past the cutoff, + voids the remaining obligation chain past it (pending and classified + rows), and rewrites the SumEquals rule to prove the truncated curve. + History at or before the cutoff is untouched. + + When the derecognition entry still needs to be booked, use + `create-event-block(event_type='asset_disposed')` instead — the + disposal handler posts it atomically with the same obligation void. + + 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 | OperationEnvelopeTerminateScheduleResponse] + """ + + 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: TerminateScheduleRequest, + idempotency_key: None | str | Unset = UNSET, +) -> ErrorResponse | OperationEnvelopeTerminateScheduleResponse | None: + """Terminate Schedule Early (No Entry) + + End a schedule early at a month-end cutoff without booking any entry. In one transaction: deletes + forward facts past the cutoff (refusing when posted entries exist past it; stale drafts past it are + deleted), voids the remaining obligation chain past the cutoff (pending and classified rows), and + rewrites the SumEquals rule to prove the truncated curve. History at or before the cutoff is + untouched, so open months the schedule still covers close normally. Use this when the termination's + GL effect is already booked (an asset transferred via a manual entry, a prepaid refunded in the + source system) or none is wanted; when the derecognition entry still needs to be booked, use create- + event-block(event_type='asset_disposed') instead — the disposal handler posts it atomically with the + same obligation void. Run BEFORE promote-obligations at close so terminated periods are never + drafted. + + **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 (TerminateScheduleRequest): End a schedule early at a month-end cutoff — no entry is + booked. + + The no-entry half of schedule retirement, for terminations whose GL + effect is already booked (an asset transferred via a manual journal + entry, a prepaid refunded in the source system) or where none is + wanted. In one transaction: deletes forward facts past the cutoff, + voids the remaining obligation chain past it (pending and classified + rows), and rewrites the SumEquals rule to prove the truncated curve. + History at or before the cutoff is untouched. + + When the derecognition entry still needs to be booked, use + `create-event-block(event_type='asset_disposed')` instead — the + disposal handler posts it atomically with the same obligation void. + + 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 | OperationEnvelopeTerminateScheduleResponse + """ + + 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: TerminateScheduleRequest, + idempotency_key: None | str | Unset = UNSET, +) -> Response[ErrorResponse | OperationEnvelopeTerminateScheduleResponse]: + """Terminate Schedule Early (No Entry) + + End a schedule early at a month-end cutoff without booking any entry. In one transaction: deletes + forward facts past the cutoff (refusing when posted entries exist past it; stale drafts past it are + deleted), voids the remaining obligation chain past the cutoff (pending and classified rows), and + rewrites the SumEquals rule to prove the truncated curve. History at or before the cutoff is + untouched, so open months the schedule still covers close normally. Use this when the termination's + GL effect is already booked (an asset transferred via a manual entry, a prepaid refunded in the + source system) or none is wanted; when the derecognition entry still needs to be booked, use create- + event-block(event_type='asset_disposed') instead — the disposal handler posts it atomically with the + same obligation void. Run BEFORE promote-obligations at close so terminated periods are never + drafted. + + **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 (TerminateScheduleRequest): End a schedule early at a month-end cutoff — no entry is + booked. + + The no-entry half of schedule retirement, for terminations whose GL + effect is already booked (an asset transferred via a manual journal + entry, a prepaid refunded in the source system) or where none is + wanted. In one transaction: deletes forward facts past the cutoff, + voids the remaining obligation chain past it (pending and classified + rows), and rewrites the SumEquals rule to prove the truncated curve. + History at or before the cutoff is untouched. + + When the derecognition entry still needs to be booked, use + `create-event-block(event_type='asset_disposed')` instead — the + disposal handler posts it atomically with the same obligation void. + + 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 | OperationEnvelopeTerminateScheduleResponse] + """ + + 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: TerminateScheduleRequest, + idempotency_key: None | str | Unset = UNSET, +) -> ErrorResponse | OperationEnvelopeTerminateScheduleResponse | None: + """Terminate Schedule Early (No Entry) + + End a schedule early at a month-end cutoff without booking any entry. In one transaction: deletes + forward facts past the cutoff (refusing when posted entries exist past it; stale drafts past it are + deleted), voids the remaining obligation chain past the cutoff (pending and classified rows), and + rewrites the SumEquals rule to prove the truncated curve. History at or before the cutoff is + untouched, so open months the schedule still covers close normally. Use this when the termination's + GL effect is already booked (an asset transferred via a manual entry, a prepaid refunded in the + source system) or none is wanted; when the derecognition entry still needs to be booked, use create- + event-block(event_type='asset_disposed') instead — the disposal handler posts it atomically with the + same obligation void. Run BEFORE promote-obligations at close so terminated periods are never + drafted. + + **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 (TerminateScheduleRequest): End a schedule early at a month-end cutoff — no entry is + booked. + + The no-entry half of schedule retirement, for terminations whose GL + effect is already booked (an asset transferred via a manual journal + entry, a prepaid refunded in the source system) or where none is + wanted. In one transaction: deletes forward facts past the cutoff, + voids the remaining obligation chain past it (pending and classified + rows), and rewrites the SumEquals rule to prove the truncated curve. + History at or before the cutoff is untouched. + + When the derecognition entry still needs to be booked, use + `create-event-block(event_type='asset_disposed')` instead — the + disposal handler posts it atomically with the same obligation void. + + 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 | OperationEnvelopeTerminateScheduleResponse + """ + + return ( + await asyncio_detailed( + graph_id=graph_id, + client=client, + body=body, + idempotency_key=idempotency_key, + ) + ).parsed diff --git a/robosystems_client/api/graphs/get_graph_capacity.py b/robosystems_client/api/graphs/get_graph_capacity.py index bb2c03a..7e9682c 100644 --- a/robosystems_client/api/graphs/get_graph_capacity.py +++ b/robosystems_client/api/graphs/get_graph_capacity.py @@ -76,8 +76,7 @@ def sync_detailed( ) -> Response[ErrorResponse | GraphCapacityResponse]: """Get Graph Tier Capacity - Status per tier: `ready` (slot available), `scalable` (can provision, 3-5 min), `at_capacity` - (contact support). Cached 60s. + Status per tier: `ready` (slot available) or `at_capacity` (contact support). Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. @@ -102,8 +101,7 @@ def sync( ) -> ErrorResponse | GraphCapacityResponse | None: """Get Graph Tier Capacity - Status per tier: `ready` (slot available), `scalable` (can provision, 3-5 min), `at_capacity` - (contact support). Cached 60s. + Status per tier: `ready` (slot available) or `at_capacity` (contact support). Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. @@ -124,8 +122,7 @@ async def asyncio_detailed( ) -> Response[ErrorResponse | GraphCapacityResponse]: """Get Graph Tier Capacity - Status per tier: `ready` (slot available), `scalable` (can provision, 3-5 min), `at_capacity` - (contact support). Cached 60s. + Status per tier: `ready` (slot available) or `at_capacity` (contact support). Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. @@ -148,8 +145,7 @@ async def asyncio( ) -> ErrorResponse | GraphCapacityResponse | None: """Get Graph Tier Capacity - Status per tier: `ready` (slot available), `scalable` (can provision, 3-5 min), `at_capacity` - (contact support). Cached 60s. + Status per tier: `ready` (slot available) or `at_capacity` (contact support). Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. diff --git a/robosystems_client/api/query/execute_sql.py b/robosystems_client/api/query/execute_sql.py index 72b7486..cc3d181 100644 --- a/robosystems_client/api/query/execute_sql.py +++ b/robosystems_client/api/query/execute_sql.py @@ -109,7 +109,7 @@ def sync_detailed( SQL over the graph's columnar tables (DuckDB) — a relational lens on the same graph-centric data, often ahead of the materialized graph. Use `?` placeholders with the `parameters` array to prevent - injection. Read-only (SELECT only), 30s timeout, 10K row limit. Not available on shared + injection. Read-only (SELECT only), 30s timeout, 10,000 row limit. Not available on shared repositories. Args: @@ -146,7 +146,7 @@ def sync( SQL over the graph's columnar tables (DuckDB) — a relational lens on the same graph-centric data, often ahead of the materialized graph. Use `?` placeholders with the `parameters` array to prevent - injection. Read-only (SELECT only), 30s timeout, 10K row limit. Not available on shared + injection. Read-only (SELECT only), 30s timeout, 10,000 row limit. Not available on shared repositories. Args: @@ -178,7 +178,7 @@ async def asyncio_detailed( SQL over the graph's columnar tables (DuckDB) — a relational lens on the same graph-centric data, often ahead of the materialized graph. Use `?` placeholders with the `parameters` array to prevent - injection. Read-only (SELECT only), 30s timeout, 10K row limit. Not available on shared + injection. Read-only (SELECT only), 30s timeout, 10,000 row limit. Not available on shared repositories. Args: @@ -213,7 +213,7 @@ async def asyncio( SQL over the graph's columnar tables (DuckDB) — a relational lens on the same graph-centric data, often ahead of the materialized graph. Use `?` placeholders with the `parameters` array to prevent - injection. Read-only (SELECT only), 30s timeout, 10K row limit. Not available on shared + injection. Read-only (SELECT only), 30s timeout, 10,000 row limit. Not available on shared repositories. Args: diff --git a/robosystems_client/api/user/list_user_api_keys.py b/robosystems_client/api/user/list_user_api_keys.py index 1d01bb6..ebba0ad 100644 --- a/robosystems_client/api/user/list_user_api_keys.py +++ b/robosystems_client/api/user/list_user_api_keys.py @@ -76,6 +76,9 @@ def sync_detailed( ) -> Response[APIKeysResponse | ErrorResponse]: """List API Keys + Lists active keys only. Revoked keys are omitted — revocation is permanent, so a revoked key never + returns to this list. + 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. @@ -99,6 +102,9 @@ def sync( ) -> APIKeysResponse | ErrorResponse | None: """List API Keys + Lists active keys only. Revoked keys are omitted — revocation is permanent, so a revoked key never + returns to this list. + 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. @@ -118,6 +124,9 @@ async def asyncio_detailed( ) -> Response[APIKeysResponse | ErrorResponse]: """List API Keys + Lists active keys only. Revoked keys are omitted — revocation is permanent, so a revoked key never + returns to this list. + 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. @@ -139,6 +148,9 @@ async def asyncio( ) -> APIKeysResponse | ErrorResponse | None: """List API Keys + Lists active keys only. Revoked keys are omitted — revocation is permanent, so a revoked key never + returns to this list. + 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. diff --git a/robosystems_client/api/user/update_user.py b/robosystems_client/api/user/update_user.py index 07ef6f7..ca308df 100644 --- a/robosystems_client/api/user/update_user.py +++ b/robosystems_client/api/user/update_user.py @@ -101,6 +101,10 @@ def sync_detailed( Args: body (UpdateUserRequest): Request model for updating user profile. + Changing ``email`` re-authenticates: a fresh proof (password re-entry or a + ``mgmt``-flow passkey assertion) must accompany the request, exactly as + passkey enrollment and removal require. Name-only updates need no proof. + 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. @@ -130,6 +134,10 @@ def sync( Args: body (UpdateUserRequest): Request model for updating user profile. + Changing ``email`` re-authenticates: a fresh proof (password re-entry or a + ``mgmt``-flow passkey assertion) must accompany the request, exactly as + passkey enrollment and removal require. Name-only updates need no proof. + 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. @@ -154,6 +162,10 @@ async def asyncio_detailed( Args: body (UpdateUserRequest): Request model for updating user profile. + Changing ``email`` re-authenticates: a fresh proof (password re-entry or a + ``mgmt``-flow passkey assertion) must accompany the request, exactly as + passkey enrollment and removal require. Name-only updates need no proof. + 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. @@ -181,6 +193,10 @@ async def asyncio( Args: body (UpdateUserRequest): Request model for updating user profile. + Changing ``email`` re-authenticates: a fresh proof (password re-entry or a + ``mgmt``-flow passkey assertion) must accompany the request, exactly as + passkey enrollment and removal require. Name-only updates need no proof. + 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. diff --git a/robosystems_client/graphql/schema.graphql b/robosystems_client/graphql/schema.graphql index 41aa09d..9100733 100644 --- a/robosystems_client/graphql/schema.graphql +++ b/robosystems_client/graphql/schema.graphql @@ -1084,6 +1084,11 @@ type PeriodCloseStatus { schedules: [PeriodCloseItem!]! totalDraft: Int! totalPosted: Int! + + """ + Receipt stamped by the close that locked this period: entries_posted, the entries_published_to_qb / entries_posted_locally split, statement stamping and rule summaries, closed_at/closed_by. Null while the period is open, and null for periods closed before receipts shipped (a closed period without a receipt is not a failed close). This is the authoritative record of what a close did — read it rather than retrying when a close's response was lost in transport. + """ + closeReceipt: CloseReceipt } """ @@ -1103,6 +1108,55 @@ type PeriodCloseItem { reversalStatus: String } +""" +What a close actually did, stamped on the period row that close locked. + +The close result used to exist only in the HTTP response, so a close +that SUCCEEDED but whose transport failed left no record and the +operator reconstructed it from separate state reads. This is that +record. Written in the same transaction as the period's `status='closed'` +flip, so a closed period and its receipt can never disagree. + +Typed rather than a free dict because it is a contract: the GraphQL +schema and both SDKs derive from it, and an opaque blob would push the +shape onto every reader to rediscover. +""" +type CloseReceipt { + """Receipt schema version; 1 is the first shipped shape""" + version: Int! + + """Period this receipt is for (YYYY-MM)""" + period: String! + closedAt: DateTime! + + """Actor id that ran the close""" + closedBy: String! + + """'user' for REST callers, 'agent' for MCP-driven closes""" + actorType: String! + + """Whether this close re-closed a previously closed period""" + wasReclose: Boolean! + + """ + Total entries the close transitioned to posted, across both post paths — the sum of the two fields below + """ + entriesPosted: Int! + entriesPublishedToQb: Int! + entriesPostedLocally: Int! + targetAutoAdvanced: Boolean! + + """Schedule rule outcomes: pass/fail/error/skipped counts""" + ruleSummary: JSON + evaluatedStructureIds: [String!]! + statementsStamped: Boolean! + statementStampNote: String + + """structure_id -> minted fact_set_id""" + stampedStatementSets: JSON! + statementRuleSummary: JSON +} + """Current fiscal calendar state for a graph.""" type FiscalCalendar { graphId: String! @@ -1202,6 +1256,11 @@ type FiscalPeriodSummary { """'open' | 'closing' | 'closed'""" status: String! closedAt: DateTime + + """ + Whether this period carries a close receipt. A flag rather than the receipt itself keeps the calendar listing compact; fetch the receipt from `get-period-close-status` for the period. False on open periods and on periods closed before receipts shipped. + """ + hasCloseReceipt: Boolean! } """All draft entries for a fiscal period, ready for review before close.""" diff --git a/robosystems_client/models/__init__.py b/robosystems_client/models/__init__.py index c8bd0b4..22fb379 100644 --- a/robosystems_client/models/__init__.py +++ b/robosystems_client/models/__init__.py @@ -111,6 +111,7 @@ from .create_event_handler_request_origin import CreateEventHandlerRequestOrigin from .create_forecast_arm import CreateForecastArm from .create_forecast_request import CreateForecastRequest +from .create_forecast_request_base_anchor import CreateForecastRequestBaseAnchor from .create_forecast_request_scenario_kind import CreateForecastRequestScenarioKind from .create_graph_request import CreateGraphRequest from .create_invitation_request import CreateInvitationRequest @@ -243,6 +244,7 @@ from .fiscal_calendar_response import FiscalCalendarResponse from .fiscal_period_summary import FiscalPeriodSummary from .forecast_mechanics import ForecastMechanics +from .forecast_mechanics_base_anchor import ForecastMechanicsBaseAnchor from .forecast_mechanics_scenario_kind import ForecastMechanicsScenarioKind from .forecast_month_lite import ForecastMonthLite from .forget_op import ForgetOp @@ -590,6 +592,12 @@ from .operation_envelope_taxonomy_block_envelope_status import ( OperationEnvelopeTaxonomyBlockEnvelopeStatus, ) +from .operation_envelope_terminate_schedule_response import ( + OperationEnvelopeTerminateScheduleResponse, +) +from .operation_envelope_terminate_schedule_response_status import ( + OperationEnvelopeTerminateScheduleResponseStatus, +) from .operation_envelope_view_response import OperationEnvelopeViewResponse from .operation_envelope_view_response_status import OperationEnvelopeViewResponseStatus from .operation_envelopelist_publish_list_member_response import ( @@ -737,7 +745,6 @@ from .search_hit import SearchHit from .search_request import SearchRequest from .search_response import SearchResponse -from .sec_connection_config import SECConnectionConfig from .security_lite import SecurityLite from .security_response import SecurityResponse from .security_response_terms import SecurityResponseTerms @@ -822,6 +829,8 @@ from .taxonomy_block_structure_request_metadata import ( TaxonomyBlockStructureRequestMetadata, ) +from .terminate_schedule_request import TerminateScheduleRequest +from .terminate_schedule_response import TerminateScheduleResponse from .tier_capacity import TierCapacity from .token_pricing import TokenPricing from .transaction_preview import TransactionPreview @@ -857,6 +866,9 @@ ) from .update_forecast_arm import UpdateForecastArm from .update_forecast_request import UpdateForecastRequest +from .update_forecast_request_base_anchor_type_0 import ( + UpdateForecastRequestBaseAnchorType0, +) from .update_forecast_request_scenario_kind_type_0 import ( UpdateForecastRequestScenarioKindType0, ) @@ -885,6 +897,9 @@ from .update_security_operation_terms_type_0 import UpdateSecurityOperationTermsType0 from .update_taxonomy_block_request import UpdateTaxonomyBlockRequest from .update_user_request import UpdateUserRequest +from .update_user_request_reauth_assertion_type_0 import ( + UpdateUserRequestReauthAssertionType0, +) from .upgrade_subscription_request import UpgradeSubscriptionRequest from .user_graphs_response import UserGraphsResponse from .user_response import UserResponse @@ -995,6 +1010,7 @@ "CreateEventHandlerRequestOrigin", "CreateForecastArm", "CreateForecastRequest", + "CreateForecastRequestBaseAnchor", "CreateForecastRequestScenarioKind", "CreateGraphRequest", "CreateInvitationRequest", @@ -1107,6 +1123,7 @@ "FiscalCalendarResponse", "FiscalPeriodSummary", "ForecastMechanics", + "ForecastMechanicsBaseAnchor", "ForecastMechanicsScenarioKind", "ForecastMonthLite", "ForgetOp", @@ -1292,6 +1309,8 @@ "OperationEnvelopeStatus", "OperationEnvelopeTaxonomyBlockEnvelope", "OperationEnvelopeTaxonomyBlockEnvelopeStatus", + "OperationEnvelopeTerminateScheduleResponse", + "OperationEnvelopeTerminateScheduleResponseStatus", "OperationEnvelopeViewResponse", "OperationEnvelopeViewResponseStatus", "OperationError", @@ -1413,7 +1432,6 @@ "SearchHit", "SearchRequest", "SearchResponse", - "SECConnectionConfig", "SecurityLite", "SecurityResponse", "SecurityResponseTerms", @@ -1476,6 +1494,8 @@ "TaxonomyBlockStructureRequestBlockType", "TaxonomyBlockStructureRequestConceptArrangementType0", "TaxonomyBlockStructureRequestMetadata", + "TerminateScheduleRequest", + "TerminateScheduleResponse", "TierCapacity", "TokenPricing", "TransactionPreview", @@ -1501,6 +1521,7 @@ "UpdateEventHandlerRequestMetadataPatch", "UpdateForecastArm", "UpdateForecastRequest", + "UpdateForecastRequestBaseAnchorType0", "UpdateForecastRequestScenarioKindType0", "UpdateGraphMemberRoleRequest", "UpdateGraphMetadataOp", @@ -1525,6 +1546,7 @@ "UpdateSecurityOperationTermsType0", "UpdateTaxonomyBlockRequest", "UpdateUserRequest", + "UpdateUserRequestReauthAssertionType0", "UpgradeSubscriptionRequest", "UserGraphsResponse", "UserResponse", diff --git a/robosystems_client/models/analytical_statement_fact_row.py b/robosystems_client/models/analytical_statement_fact_row.py index a12cf09..3214c04 100644 --- a/robosystems_client/models/analytical_statement_fact_row.py +++ b/robosystems_client/models/analytical_statement_fact_row.py @@ -20,6 +20,7 @@ class AnalyticalStatementFactRow: name (str): canonical_concept (None | str | Unset): value (float | None | Unset): + start_date (None | str | Unset): end_date (None | str | Unset): period_type (None | str | Unset): duration_type (None | str | Unset): @@ -29,6 +30,7 @@ class AnalyticalStatementFactRow: name: str canonical_concept: None | str | Unset = UNSET value: float | None | Unset = UNSET + start_date: None | str | Unset = UNSET end_date: None | str | Unset = UNSET period_type: None | str | Unset = UNSET duration_type: None | str | Unset = UNSET @@ -51,6 +53,12 @@ def to_dict(self) -> dict[str, Any]: else: value = self.value + start_date: None | str | Unset + if isinstance(self.start_date, Unset): + start_date = UNSET + else: + start_date = self.start_date + end_date: None | str | Unset if isinstance(self.end_date, Unset): end_date = UNSET @@ -81,6 +89,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["canonical_concept"] = canonical_concept if value is not UNSET: field_dict["value"] = value + if start_date is not UNSET: + field_dict["start_date"] = start_date if end_date is not UNSET: field_dict["end_date"] = end_date if period_type is not UNSET: @@ -115,6 +125,15 @@ def _parse_value(data: object) -> float | None | Unset: value = _parse_value(d.pop("value", UNSET)) + def _parse_start_date(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + start_date = _parse_start_date(d.pop("start_date", UNSET)) + def _parse_end_date(data: object) -> None | str | Unset: if data is None: return data @@ -147,6 +166,7 @@ def _parse_duration_type(data: object) -> None | str | Unset: name=name, canonical_concept=canonical_concept, value=value, + start_date=start_date, end_date=end_date, period_type=period_type, duration_type=duration_type, diff --git a/robosystems_client/models/backup_response.py b/robosystems_client/models/backup_response.py index 988293b..633e618 100644 --- a/robosystems_client/models/backup_response.py +++ b/robosystems_client/models/backup_response.py @@ -32,7 +32,8 @@ class BackupResponse: completed_at (None | str): expires_at (None | str): initiated_by (str | Unset): Who started this backup. 'user' is one you requested and it counts against the - tier's daily backup limit; 'scheduled' is taken nightly on your behalf and does not. Default: 'user'. + tier's daily backup limit; 'scheduled' is taken nightly on your behalf and does not; 'final' is the copy taken + when a graph is deprovisioned, so you can still retrieve your data afterwards. Default: 'user'. memory_included (bool | None | Unset): Whether the archive carries this graph's semantic memory store. Null for backups taken before memory was included, which make no claim either way — distinct from false, which means the graph had none. diff --git a/robosystems_client/models/compute_forecast_response.py b/robosystems_client/models/compute_forecast_response.py index 628d10e..aefa131 100644 --- a/robosystems_client/models/compute_forecast_response.py +++ b/robosystems_client/models/compute_forecast_response.py @@ -24,7 +24,11 @@ class ComputeForecastResponse: structure_id (str): scenario_id (str): The scenario key every emitted FactSet carries — the forecast block's own structure id. entity_id (str): - base_period (str): Seed month the walk projected from. + base_period (str): Origin month of the block's authored horizon window — where its levers are keyed from. Equal + to ``anchor_period`` unless the walk re-anchored at the seam. + anchor_period (str): Month the walk actually seeded its opening balances from. With ``base_anchor='seam'`` this + advances to the newest closed month as periods close, so the first forward month rolls off real balances instead + of a stale base; with ``'fixed'`` it always equals ``base_period``. months (int): Forward months requested. months_computed (list[ForecastMonthLite] | Unset): halted_at (None | str | Unset): Month (``YYYY-MM``) where the walk stopped because verification failed, or null @@ -41,6 +45,7 @@ class ComputeForecastResponse: scenario_id: str entity_id: str base_period: str + anchor_period: str months: int months_computed: list[ForecastMonthLite] | Unset = UNSET halted_at: None | str | Unset = UNSET @@ -57,6 +62,8 @@ def to_dict(self) -> dict[str, Any]: base_period = self.base_period + anchor_period = self.anchor_period + months = self.months months_computed: list[dict[str, Any]] | Unset = UNSET @@ -91,6 +98,7 @@ def to_dict(self) -> dict[str, Any]: "scenario_id": scenario_id, "entity_id": entity_id, "base_period": base_period, + "anchor_period": anchor_period, "months": months, } ) @@ -119,6 +127,8 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: base_period = d.pop("base_period") + anchor_period = d.pop("anchor_period") + months = d.pop("months") _months_computed = d.pop("months_computed", UNSET) @@ -155,6 +165,7 @@ def _parse_halted_at(data: object) -> None | str | Unset: scenario_id=scenario_id, entity_id=entity_id, base_period=base_period, + anchor_period=anchor_period, months=months, months_computed=months_computed, halted_at=halted_at, diff --git a/robosystems_client/models/connection_provider_info_provider.py b/robosystems_client/models/connection_provider_info_provider.py index 3a3dfb4..9816457 100644 --- a/robosystems_client/models/connection_provider_info_provider.py +++ b/robosystems_client/models/connection_provider_info_provider.py @@ -4,7 +4,6 @@ class ConnectionProviderInfoProvider(str, Enum): EXTERNAL = "external" QUICKBOOKS = "quickbooks" - SEC = "sec" def __str__(self) -> str: return str(self.value) diff --git a/robosystems_client/models/create_connection_request.py b/robosystems_client/models/create_connection_request.py index 7fd34af..91cc7e3 100644 --- a/robosystems_client/models/create_connection_request.py +++ b/robosystems_client/models/create_connection_request.py @@ -12,7 +12,6 @@ if TYPE_CHECKING: from ..models.external_connection_config import ExternalConnectionConfig from ..models.quick_books_connection_config import QuickBooksConnectionConfig - from ..models.sec_connection_config import SECConnectionConfig T = TypeVar("T", bound="CreateConnectionRequest") @@ -24,16 +23,13 @@ class CreateConnectionRequest: Attributes: provider (CreateConnectionRequestProvider): Connection provider type - entity_id (None | str | Unset): Entity identifier. Required for QuickBooks, optional for SEC (SEC creates the - entity from filing data). - sec_config (None | SECConnectionConfig | Unset): + entity_id (None | str | Unset): Entity identifier. Required for QuickBooks. quickbooks_config (None | QuickBooksConnectionConfig | Unset): external_config (ExternalConnectionConfig | None | Unset): """ provider: CreateConnectionRequestProvider entity_id: None | str | Unset = UNSET - sec_config: None | SECConnectionConfig | Unset = UNSET quickbooks_config: None | QuickBooksConnectionConfig | Unset = UNSET external_config: ExternalConnectionConfig | None | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -41,7 +37,6 @@ class CreateConnectionRequest: def to_dict(self) -> dict[str, Any]: from ..models.external_connection_config import ExternalConnectionConfig from ..models.quick_books_connection_config import QuickBooksConnectionConfig - from ..models.sec_connection_config import SECConnectionConfig provider = self.provider.value @@ -51,14 +46,6 @@ def to_dict(self) -> dict[str, Any]: else: entity_id = self.entity_id - sec_config: dict[str, Any] | None | Unset - if isinstance(self.sec_config, Unset): - sec_config = UNSET - elif isinstance(self.sec_config, SECConnectionConfig): - sec_config = self.sec_config.to_dict() - else: - sec_config = self.sec_config - quickbooks_config: dict[str, Any] | None | Unset if isinstance(self.quickbooks_config, Unset): quickbooks_config = UNSET @@ -84,8 +71,6 @@ def to_dict(self) -> dict[str, Any]: ) if entity_id is not UNSET: field_dict["entity_id"] = entity_id - if sec_config is not UNSET: - field_dict["sec_config"] = sec_config if quickbooks_config is not UNSET: field_dict["quickbooks_config"] = quickbooks_config if external_config is not UNSET: @@ -97,7 +82,6 @@ def to_dict(self) -> dict[str, Any]: def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: from ..models.external_connection_config import ExternalConnectionConfig from ..models.quick_books_connection_config import QuickBooksConnectionConfig - from ..models.sec_connection_config import SECConnectionConfig d = dict(src_dict) provider = CreateConnectionRequestProvider(d.pop("provider")) @@ -111,23 +95,6 @@ def _parse_entity_id(data: object) -> None | str | Unset: entity_id = _parse_entity_id(d.pop("entity_id", UNSET)) - def _parse_sec_config(data: object) -> None | SECConnectionConfig | Unset: - if data is None: - return data - if isinstance(data, Unset): - return data - try: - if not isinstance(data, dict): - raise TypeError() - sec_config_type_0 = SECConnectionConfig.from_dict(data) - - return sec_config_type_0 - except (TypeError, ValueError, AttributeError, KeyError): - pass - return cast(None | SECConnectionConfig | Unset, data) - - sec_config = _parse_sec_config(d.pop("sec_config", UNSET)) - def _parse_quickbooks_config( data: object, ) -> None | QuickBooksConnectionConfig | Unset: @@ -167,7 +134,6 @@ def _parse_external_config(data: object) -> ExternalConnectionConfig | None | Un create_connection_request = cls( provider=provider, entity_id=entity_id, - sec_config=sec_config, quickbooks_config=quickbooks_config, external_config=external_config, ) diff --git a/robosystems_client/models/create_connection_request_provider.py b/robosystems_client/models/create_connection_request_provider.py index 8d1265b..3efddf4 100644 --- a/robosystems_client/models/create_connection_request_provider.py +++ b/robosystems_client/models/create_connection_request_provider.py @@ -4,7 +4,6 @@ class CreateConnectionRequestProvider(str, Enum): EXTERNAL = "external" QUICKBOOKS = "quickbooks" - SEC = "sec" def __str__(self) -> str: return str(self.value) diff --git a/robosystems_client/models/create_forecast_request.py b/robosystems_client/models/create_forecast_request.py index 214bf02..89e4a96 100644 --- a/robosystems_client/models/create_forecast_request.py +++ b/robosystems_client/models/create_forecast_request.py @@ -6,6 +6,7 @@ from attrs import define as _attrs_define from attrs import field as _attrs_field +from ..models.create_forecast_request_base_anchor import CreateForecastRequestBaseAnchor from ..models.create_forecast_request_scenario_kind import ( CreateForecastRequestScenarioKind, ) @@ -38,7 +39,14 @@ class CreateForecastRequest: horizon_months (int | Unset): Forward months to project past the base period. Default: 12. base_period (None | str | Unset): Seed month (``YYYY-MM``) the walk projects forward from. Defaults to the fiscal calendar's closed-through period, else the newest actual report month. Resolved and stored at create - time. + time, and it never moves afterwards — every lever is keyed to a month inside ``base_period + 1 … + + horizon_months``, so moving it would mean restating all of them. ``base_anchor`` decides whether the walk still + *seeds* here once months close under it. + base_anchor (CreateForecastRequestBaseAnchor | Unset): Where the walk takes its opening balances as periods + close. ``seam`` (default) re-anchors on the newest closed month inside the horizon, so the scenario survives a + close untouched and its first forward month rolls off real balances. ``fixed`` pins the walk to ``base_period`` + — the deliberate counterfactual, whose balances are meant to diverge from actuals. Default: + CreateForecastRequestBaseAnchor.SEAM. line_assertions (list[LineAssertionRequest] | Unset): Direct statement-line assertions (manual overrides). Each names a calc-DAG leaf and wins over driver rules and carry-forward for the months it asserts. line_growth (list[LineGrowthRequest] | Unset): Per-line growth trajectories. Each names an income-statement leaf @@ -55,6 +63,9 @@ class CreateForecastRequest: ) horizon_months: int | Unset = 12 base_period: None | str | Unset = UNSET + base_anchor: CreateForecastRequestBaseAnchor | Unset = ( + CreateForecastRequestBaseAnchor.SEAM + ) line_assertions: list[LineAssertionRequest] | Unset = UNSET line_growth: list[LineGrowthRequest] | Unset = UNSET entity_id: None | str | Unset = UNSET @@ -80,6 +91,10 @@ def to_dict(self) -> dict[str, Any]: else: base_period = self.base_period + base_anchor: str | Unset = UNSET + if not isinstance(self.base_anchor, Unset): + base_anchor = self.base_anchor.value + line_assertions: list[dict[str, Any]] | Unset = UNSET if not isinstance(self.line_assertions, Unset): line_assertions = [] @@ -114,6 +129,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["horizon_months"] = horizon_months if base_period is not UNSET: field_dict["base_period"] = base_period + if base_anchor is not UNSET: + field_dict["base_anchor"] = base_anchor if line_assertions is not UNSET: field_dict["line_assertions"] = line_assertions if line_growth is not UNSET: @@ -157,6 +174,13 @@ def _parse_base_period(data: object) -> None | str | Unset: base_period = _parse_base_period(d.pop("base_period", UNSET)) + _base_anchor = d.pop("base_anchor", UNSET) + base_anchor: CreateForecastRequestBaseAnchor | Unset + if isinstance(_base_anchor, Unset): + base_anchor = UNSET + else: + base_anchor = CreateForecastRequestBaseAnchor(_base_anchor) + _line_assertions = d.pop("line_assertions", UNSET) line_assertions: list[LineAssertionRequest] | Unset = UNSET if _line_assertions is not UNSET: @@ -190,6 +214,7 @@ def _parse_entity_id(data: object) -> None | str | Unset: scenario_kind=scenario_kind, horizon_months=horizon_months, base_period=base_period, + base_anchor=base_anchor, line_assertions=line_assertions, line_growth=line_growth, entity_id=entity_id, diff --git a/robosystems_client/models/create_forecast_request_base_anchor.py b/robosystems_client/models/create_forecast_request_base_anchor.py new file mode 100644 index 0000000..16891f0 --- /dev/null +++ b/robosystems_client/models/create_forecast_request_base_anchor.py @@ -0,0 +1,9 @@ +from enum import Enum + + +class CreateForecastRequestBaseAnchor(str, Enum): + FIXED = "fixed" + SEAM = "seam" + + def __str__(self) -> str: + return str(self.value) diff --git a/robosystems_client/models/create_taxonomy_block_request.py b/robosystems_client/models/create_taxonomy_block_request.py index 0305e82..7f3073b 100644 --- a/robosystems_client/models/create_taxonomy_block_request.py +++ b/robosystems_client/models/create_taxonomy_block_request.py @@ -36,8 +36,7 @@ class CreateTaxonomyBlockRequest: extends a library taxonomy) and ignored otherwise. The library path (seeding ``reporting_standard`` rows) does NOT flow - through this envelope — it uses a dedicated library writer that bypasses - these caps and tenant scoping. + through this envelope; library content is not tenant-writable here. Attributes: name (str): Taxonomy display name. diff --git a/robosystems_client/models/delete_schedule_arm.py b/robosystems_client/models/delete_schedule_arm.py index bc710a5..9ec2cf3 100644 --- a/robosystems_client/models/delete_schedule_arm.py +++ b/robosystems_client/models/delete_schedule_arm.py @@ -25,9 +25,11 @@ class DeleteScheduleArm: Hard deletes the Structure, all Facts tied to it, and all Associations tied to it. This is a permanent, irreversible - operation. For ending a schedule early without removing history, - fire `create-event-block(event_type='asset_disposed')` instead — the - handler truncates the schedule + posts the disposal entry atomically. + operation. For ending a schedule early without removing history, use + `terminate-schedule` (no entry) or + `create-event-block(event_type='asset_disposed')` (the handler voids + the remaining obligation chain + posts the disposal entry atomically; + recognized facts stay as history). """ block_type: Literal["schedule"] diff --git a/robosystems_client/models/delete_schedule_request.py b/robosystems_client/models/delete_schedule_request.py index 6a1f009..1f10619 100644 --- a/robosystems_client/models/delete_schedule_request.py +++ b/robosystems_client/models/delete_schedule_request.py @@ -15,9 +15,11 @@ class DeleteScheduleRequest: Hard deletes the Structure, all Facts tied to it, and all Associations tied to it. This is a permanent, irreversible - operation. For ending a schedule early without removing history, - fire `create-event-block(event_type='asset_disposed')` instead — the - handler truncates the schedule + posts the disposal entry atomically. + operation. For ending a schedule early without removing history, use + `terminate-schedule` (no entry) or + `create-event-block(event_type='asset_disposed')` (the handler voids + the remaining obligation chain + posts the disposal entry atomically; + recognized facts stay as history). Attributes: structure_id (str): diff --git a/robosystems_client/models/fiscal_period_summary.py b/robosystems_client/models/fiscal_period_summary.py index 8cf16ab..925738a 100644 --- a/robosystems_client/models/fiscal_period_summary.py +++ b/robosystems_client/models/fiscal_period_summary.py @@ -26,6 +26,9 @@ class FiscalPeriodSummary: end_date (datetime.date): status (str): 'open' | 'closing' | 'closed' closed_at (datetime.datetime | None | Unset): + has_close_receipt (bool | Unset): Whether this period carries a close receipt. A flag rather than the receipt + itself keeps the calendar listing compact; fetch the receipt from `get-period-close-status` for the period. + False on open periods and on periods closed before receipts shipped. Default: False. """ name: str @@ -33,6 +36,7 @@ class FiscalPeriodSummary: end_date: datetime.date status: str closed_at: datetime.datetime | None | Unset = UNSET + has_close_receipt: bool | Unset = False additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: @@ -52,6 +56,8 @@ def to_dict(self) -> dict[str, Any]: else: closed_at = self.closed_at + has_close_receipt = self.has_close_receipt + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -64,6 +70,8 @@ def to_dict(self) -> dict[str, Any]: ) if closed_at is not UNSET: field_dict["closed_at"] = closed_at + if has_close_receipt is not UNSET: + field_dict["has_close_receipt"] = has_close_receipt return field_dict @@ -95,12 +103,15 @@ def _parse_closed_at(data: object) -> datetime.datetime | None | Unset: closed_at = _parse_closed_at(d.pop("closed_at", UNSET)) + has_close_receipt = d.pop("has_close_receipt", UNSET) + fiscal_period_summary = cls( name=name, start_date=start_date, end_date=end_date, status=status, closed_at=closed_at, + has_close_receipt=has_close_receipt, ) fiscal_period_summary.additional_properties = d diff --git a/robosystems_client/models/forecast_mechanics.py b/robosystems_client/models/forecast_mechanics.py index 9f11393..d3e4882 100644 --- a/robosystems_client/models/forecast_mechanics.py +++ b/robosystems_client/models/forecast_mechanics.py @@ -6,6 +6,7 @@ from attrs import define as _attrs_define from attrs import field as _attrs_field +from ..models.forecast_mechanics_base_anchor import ForecastMechanicsBaseAnchor from ..models.forecast_mechanics_scenario_kind import ForecastMechanicsScenarioKind from ..types import UNSET, Unset @@ -34,12 +35,19 @@ class ForecastMechanics: Attributes: horizon_months (int): Forward months projected past the base period. - base_period (str): Seed month (``YYYY-MM``) the walk projects forward from — resolved at create time (request → - fiscal calendar closed-through → newest actual report month) and stored so recompute is deterministic. + base_period (str): Origin month (``YYYY-MM``) of the authored horizon window — resolved at create time (request + → fiscal calendar closed-through → newest actual report month) and stored so recompute is deterministic. Every + lever, line assertion and growth rate is keyed to a month in ``base_period + 1 … base_period + horizon_months``, + so this never moves on its own; ``base_anchor`` decides whether the *walk* still seeds here. levers (list[LeverAssertionLite]): Expanded lever assertions (authoring order). kind (Literal['forecast'] | Unset): Default: 'forecast'. scenario_kind (ForecastMechanicsScenarioKind | Unset): Scenario kind — display/filter metadata, not machinery. Default: ForecastMechanicsScenarioKind.FORECAST. + base_anchor (ForecastMechanicsBaseAnchor | Unset): Where the walk takes its opening balances. ``seam`` (default) + re-anchors on the newest closed month at or after ``base_period``, so a scenario survives a period close without + being rebuilt and its first forward month rolls off real balances. ``fixed`` pins the walk to ``base_period`` — + the deliberate counterfactual (“if we had restarted in July”), whose balances diverge from actuals on purpose. + Default: ForecastMechanicsBaseAnchor.SEAM. line_assertions (list[LineAssertionLite] | Unset): Direct statement-line assertions (authoring order) — manual overrides that win over driver rules and carry-forward for the months they name. line_growth (list[LineGrowthLite] | Unset): Per-line growth trajectories (authoring order) — each grows an @@ -55,6 +63,7 @@ class ForecastMechanics: scenario_kind: ForecastMechanicsScenarioKind | Unset = ( ForecastMechanicsScenarioKind.FORECAST ) + base_anchor: ForecastMechanicsBaseAnchor | Unset = ForecastMechanicsBaseAnchor.SEAM line_assertions: list[LineAssertionLite] | Unset = UNSET line_growth: list[LineGrowthLite] | Unset = UNSET computed_months: int | Unset = 0 @@ -76,6 +85,10 @@ def to_dict(self) -> dict[str, Any]: if not isinstance(self.scenario_kind, Unset): scenario_kind = self.scenario_kind.value + base_anchor: str | Unset = UNSET + if not isinstance(self.base_anchor, Unset): + base_anchor = self.base_anchor.value + line_assertions: list[dict[str, Any]] | Unset = UNSET if not isinstance(self.line_assertions, Unset): line_assertions = [] @@ -105,6 +118,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["kind"] = kind if scenario_kind is not UNSET: field_dict["scenario_kind"] = scenario_kind + if base_anchor is not UNSET: + field_dict["base_anchor"] = base_anchor if line_assertions is not UNSET: field_dict["line_assertions"] = line_assertions if line_growth is not UNSET: @@ -143,6 +158,13 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: else: scenario_kind = ForecastMechanicsScenarioKind(_scenario_kind) + _base_anchor = d.pop("base_anchor", UNSET) + base_anchor: ForecastMechanicsBaseAnchor | Unset + if isinstance(_base_anchor, Unset): + base_anchor = UNSET + else: + base_anchor = ForecastMechanicsBaseAnchor(_base_anchor) + _line_assertions = d.pop("line_assertions", UNSET) line_assertions: list[LineAssertionLite] | Unset = UNSET if _line_assertions is not UNSET: @@ -169,6 +191,7 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: levers=levers, kind=kind, scenario_kind=scenario_kind, + base_anchor=base_anchor, line_assertions=line_assertions, line_growth=line_growth, computed_months=computed_months, diff --git a/robosystems_client/models/forecast_mechanics_base_anchor.py b/robosystems_client/models/forecast_mechanics_base_anchor.py new file mode 100644 index 0000000..6fb3c76 --- /dev/null +++ b/robosystems_client/models/forecast_mechanics_base_anchor.py @@ -0,0 +1,9 @@ +from enum import Enum + + +class ForecastMechanicsBaseAnchor(str, Enum): + FIXED = "fixed" + SEAM = "seam" + + def __str__(self) -> str: + return str(self.value) diff --git a/robosystems_client/models/list_connections_provider_type_0.py b/robosystems_client/models/list_connections_provider_type_0.py index 5327c98..2f61ec0 100644 --- a/robosystems_client/models/list_connections_provider_type_0.py +++ b/robosystems_client/models/list_connections_provider_type_0.py @@ -4,7 +4,6 @@ class ListConnectionsProviderType0(str, Enum): EXTERNAL = "external" QUICKBOOKS = "quickbooks" - SEC = "sec" def __str__(self) -> str: return str(self.value) diff --git a/robosystems_client/models/operation_envelope_terminate_schedule_response.py b/robosystems_client/models/operation_envelope_terminate_schedule_response.py new file mode 100644 index 0000000..477f7ec --- /dev/null +++ b/robosystems_client/models/operation_envelope_terminate_schedule_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_terminate_schedule_response_status import ( + OperationEnvelopeTerminateScheduleResponseStatus, +) +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.terminate_schedule_response import TerminateScheduleResponse + + +T = TypeVar("T", bound="OperationEnvelopeTerminateScheduleResponse") + + +@_attrs_define +class OperationEnvelopeTerminateScheduleResponse: + """ + Attributes: + operation (str): Kebab-case operation name + operation_id (str): op_-prefixed ULID for audit and SSE correlation + status (OperationEnvelopeTerminateScheduleResponseStatus): Operation lifecycle state + at (str): ISO-8601 UTC timestamp + result (None | TerminateScheduleResponse | 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: OperationEnvelopeTerminateScheduleResponseStatus + at: str + result: None | TerminateScheduleResponse | 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.terminate_schedule_response import TerminateScheduleResponse + + 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, TerminateScheduleResponse): + 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.terminate_schedule_response import TerminateScheduleResponse + + d = dict(src_dict) + operation = d.pop("operation") + + operation_id = d.pop("operationId") + + status = OperationEnvelopeTerminateScheduleResponseStatus(d.pop("status")) + + at = d.pop("at") + + def _parse_result(data: object) -> None | TerminateScheduleResponse | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + result_type_0 = TerminateScheduleResponse.from_dict(data) + + return result_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(None | TerminateScheduleResponse | 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_terminate_schedule_response = cls( + operation=operation, + operation_id=operation_id, + status=status, + at=at, + result=result, + created_by=created_by, + idempotent_replay=idempotent_replay, + ) + + operation_envelope_terminate_schedule_response.additional_properties = d + return operation_envelope_terminate_schedule_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_terminate_schedule_response_status.py b/robosystems_client/models/operation_envelope_terminate_schedule_response_status.py new file mode 100644 index 0000000..0cdfea9 --- /dev/null +++ b/robosystems_client/models/operation_envelope_terminate_schedule_response_status.py @@ -0,0 +1,10 @@ +from enum import Enum + + +class OperationEnvelopeTerminateScheduleResponseStatus(str, Enum): + COMPLETED = "completed" + FAILED = "failed" + PENDING = "pending" + + def __str__(self) -> str: + return str(self.value) diff --git a/robosystems_client/models/terminate_schedule_request.py b/robosystems_client/models/terminate_schedule_request.py new file mode 100644 index 0000000..b1410f2 --- /dev/null +++ b/robosystems_client/models/terminate_schedule_request.py @@ -0,0 +1,92 @@ +from __future__ import annotations + +import datetime +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="TerminateScheduleRequest") + + +@_attrs_define +class TerminateScheduleRequest: + """End a schedule early at a month-end cutoff — no entry is booked. + + The no-entry half of schedule retirement, for terminations whose GL + effect is already booked (an asset transferred via a manual journal + entry, a prepaid refunded in the source system) or where none is + wanted. In one transaction: deletes forward facts past the cutoff, + voids the remaining obligation chain past it (pending and classified + rows), and rewrites the SumEquals rule to prove the truncated curve. + History at or before the cutoff is untouched. + + When the derecognition entry still needs to be booked, use + `create-event-block(event_type='asset_disposed')` instead — the + disposal handler posts it atomically with the same obligation void. + + Attributes: + structure_id (str): The schedule structure to terminate. + new_end_date (datetime.date): Last date the schedule covers — must be the last day of a month (schedule facts + are whole-month). Facts and obligations for periods starting after this date are removed/voided. + reason (str): Why the schedule is ending early — captured in the audit log. + """ + + structure_id: str + new_end_date: datetime.date + reason: str + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + structure_id = self.structure_id + + new_end_date = self.new_end_date.isoformat() + + reason = self.reason + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "structure_id": structure_id, + "new_end_date": new_end_date, + "reason": reason, + } + ) + + 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") + + new_end_date = datetime.date.fromisoformat(d.pop("new_end_date")) + + reason = d.pop("reason") + + terminate_schedule_request = cls( + structure_id=structure_id, + new_end_date=new_end_date, + reason=reason, + ) + + terminate_schedule_request.additional_properties = d + return terminate_schedule_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/terminate_schedule_response.py b/robosystems_client/models/terminate_schedule_response.py new file mode 100644 index 0000000..137d0f3 --- /dev/null +++ b/robosystems_client/models/terminate_schedule_response.py @@ -0,0 +1,110 @@ +from __future__ import annotations + +import datetime +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="TerminateScheduleResponse") + + +@_attrs_define +class TerminateScheduleResponse: + """ + Attributes: + structure_id (str): + name (str): + new_end_date (datetime.date): + facts_deleted (int): + obligations_voided (int): + rule_updated (bool): + reason (str): + """ + + structure_id: str + name: str + new_end_date: datetime.date + facts_deleted: int + obligations_voided: int + rule_updated: bool + reason: str + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + structure_id = self.structure_id + + name = self.name + + new_end_date = self.new_end_date.isoformat() + + facts_deleted = self.facts_deleted + + obligations_voided = self.obligations_voided + + rule_updated = self.rule_updated + + reason = self.reason + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "structure_id": structure_id, + "name": name, + "new_end_date": new_end_date, + "facts_deleted": facts_deleted, + "obligations_voided": obligations_voided, + "rule_updated": rule_updated, + "reason": reason, + } + ) + + 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") + + name = d.pop("name") + + new_end_date = datetime.date.fromisoformat(d.pop("new_end_date")) + + facts_deleted = d.pop("facts_deleted") + + obligations_voided = d.pop("obligations_voided") + + rule_updated = d.pop("rule_updated") + + reason = d.pop("reason") + + terminate_schedule_response = cls( + structure_id=structure_id, + name=name, + new_end_date=new_end_date, + facts_deleted=facts_deleted, + obligations_voided=obligations_voided, + rule_updated=rule_updated, + reason=reason, + ) + + terminate_schedule_response.additional_properties = d + return terminate_schedule_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/tier_capacity.py b/robosystems_client/models/tier_capacity.py index 11a5489..3813d11 100644 --- a/robosystems_client/models/tier_capacity.py +++ b/robosystems_client/models/tier_capacity.py @@ -16,7 +16,7 @@ class TierCapacity: Attributes: tier (str): Tier identifier (e.g. ladybug-standard) display_name (str): Human-readable tier name - status (str): Capacity status: ready, scalable, or at_capacity + status (str): Capacity status: ready or at_capacity message (str): Human-readable status message for frontend display """ diff --git a/robosystems_client/models/update_forecast_request.py b/robosystems_client/models/update_forecast_request.py index ce07410..8cbb4fd 100644 --- a/robosystems_client/models/update_forecast_request.py +++ b/robosystems_client/models/update_forecast_request.py @@ -6,6 +6,9 @@ from attrs import define as _attrs_define from attrs import field as _attrs_field +from ..models.update_forecast_request_base_anchor_type_0 import ( + UpdateForecastRequestBaseAnchorType0, +) from ..models.update_forecast_request_scenario_kind_type_0 import ( UpdateForecastRequestScenarioKindType0, ) @@ -38,6 +41,9 @@ class UpdateForecastRequest: scenario_kind (None | Unset | UpdateForecastRequestScenarioKindType0): horizon_months (int | None | Unset): base_period (None | str | Unset): + base_anchor (None | Unset | UpdateForecastRequestBaseAnchorType0): Switch the walk between seam-anchored + (default) and pinned to ``base_period``. Changes nothing about the authored window, so unlike ``base_period`` it + needs no levers re-supplied. levers (list[LeverAssertionRequest] | None | Unset): Full replacement of the lever set when provided. line_assertions (list[LineAssertionRequest] | None | Unset): Full replacement of the line-assertion set when provided. Pass an empty list to clear every assertion. @@ -50,6 +56,7 @@ class UpdateForecastRequest: scenario_kind: None | Unset | UpdateForecastRequestScenarioKindType0 = UNSET horizon_months: int | None | Unset = UNSET base_period: None | str | Unset = UNSET + base_anchor: None | Unset | UpdateForecastRequestBaseAnchorType0 = UNSET levers: list[LeverAssertionRequest] | None | Unset = UNSET line_assertions: list[LineAssertionRequest] | None | Unset = UNSET line_growth: list[LineGrowthRequest] | None | Unset = UNSET @@ -84,6 +91,14 @@ def to_dict(self) -> dict[str, Any]: else: base_period = self.base_period + base_anchor: None | str | Unset + if isinstance(self.base_anchor, Unset): + base_anchor = UNSET + elif isinstance(self.base_anchor, UpdateForecastRequestBaseAnchorType0): + base_anchor = self.base_anchor.value + else: + base_anchor = self.base_anchor + levers: list[dict[str, Any]] | None | Unset if isinstance(self.levers, Unset): levers = UNSET @@ -135,6 +150,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["horizon_months"] = horizon_months if base_period is not UNSET: field_dict["base_period"] = base_period + if base_anchor is not UNSET: + field_dict["base_anchor"] = base_anchor if levers is not UNSET: field_dict["levers"] = levers if line_assertions is not UNSET: @@ -199,6 +216,25 @@ def _parse_base_period(data: object) -> None | str | Unset: base_period = _parse_base_period(d.pop("base_period", UNSET)) + def _parse_base_anchor( + data: object, + ) -> None | Unset | UpdateForecastRequestBaseAnchorType0: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + base_anchor_type_0 = UpdateForecastRequestBaseAnchorType0(data) + + return base_anchor_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(None | Unset | UpdateForecastRequestBaseAnchorType0, data) + + base_anchor = _parse_base_anchor(d.pop("base_anchor", UNSET)) + def _parse_levers(data: object) -> list[LeverAssertionRequest] | None | Unset: if data is None: return data @@ -277,6 +313,7 @@ def _parse_line_growth(data: object) -> list[LineGrowthRequest] | None | Unset: scenario_kind=scenario_kind, horizon_months=horizon_months, base_period=base_period, + base_anchor=base_anchor, levers=levers, line_assertions=line_assertions, line_growth=line_growth, diff --git a/robosystems_client/models/update_forecast_request_base_anchor_type_0.py b/robosystems_client/models/update_forecast_request_base_anchor_type_0.py new file mode 100644 index 0000000..edf3b0b --- /dev/null +++ b/robosystems_client/models/update_forecast_request_base_anchor_type_0.py @@ -0,0 +1,9 @@ +from enum import Enum + + +class UpdateForecastRequestBaseAnchorType0(str, Enum): + FIXED = "fixed" + SEAM = "seam" + + def __str__(self) -> str: + return str(self.value) diff --git a/robosystems_client/models/update_schedule_arm.py b/robosystems_client/models/update_schedule_arm.py index b5ff6e3..2d10b82 100644 --- a/robosystems_client/models/update_schedule_arm.py +++ b/robosystems_client/models/update_schedule_arm.py @@ -28,9 +28,11 @@ class UpdateScheduleArm: Structure row / its metadata_ JSONB column). NOT editable via this op: period_start, period_end, monthly_amount. - Those require fact regeneration — fire an event block that terminates - the schedule (e.g., `asset_disposed`) and create a fresh schedule via - `create-information-block` (`block_type='schedule'`). + Those require fact regeneration — end the schedule early via + `terminate-schedule` (no entry) or + `create-event-block(event_type='asset_disposed')` (with a disposal + entry), then create a fresh schedule via `create-information-block` + (`block_type='schedule'`). Omitted fields are left unchanged. """ diff --git a/robosystems_client/models/update_schedule_request.py b/robosystems_client/models/update_schedule_request.py index 3f6f984..5014847 100644 --- a/robosystems_client/models/update_schedule_request.py +++ b/robosystems_client/models/update_schedule_request.py @@ -24,9 +24,11 @@ class UpdateScheduleRequest: Structure row / its metadata_ JSONB column). NOT editable via this op: period_start, period_end, monthly_amount. - Those require fact regeneration — fire an event block that terminates - the schedule (e.g., `asset_disposed`) and create a fresh schedule via - `create-information-block` (`block_type='schedule'`). + Those require fact regeneration — end the schedule early via + `terminate-schedule` (no entry) or + `create-event-block(event_type='asset_disposed')` (with a disposal + entry), then create a fresh schedule via `create-information-block` + (`block_type='schedule'`). Omitted fields are left unchanged. diff --git a/robosystems_client/models/update_user_request.py b/robosystems_client/models/update_user_request.py index c04b1d3..a88318f 100644 --- a/robosystems_client/models/update_user_request.py +++ b/robosystems_client/models/update_user_request.py @@ -1,13 +1,19 @@ from __future__ import annotations 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 from ..types import UNSET, Unset +if TYPE_CHECKING: + from ..models.update_user_request_reauth_assertion_type_0 import ( + UpdateUserRequestReauthAssertionType0, + ) + + T = TypeVar("T", bound="UpdateUserRequest") @@ -15,16 +21,29 @@ class UpdateUserRequest: """Request model for updating user profile. - Attributes: - name (None | str | Unset): User's display name - email (None | str | Unset): User's email address + Changing ``email`` re-authenticates: a fresh proof (password re-entry or a + ``mgmt``-flow passkey assertion) must accompany the request, exactly as + passkey enrollment and removal require. Name-only updates need no proof. + + Attributes: + name (None | str | Unset): User's display name + email (None | str | Unset): User's email address + reauth_password (None | str | Unset): Password re-entry, required to change email for a password-holding account + reauth_assertion (None | Unset | UpdateUserRequestReauthAssertionType0): A fresh mgmt-flow passkey assertion, + required to change email for a passkey-only account """ name: None | str | Unset = UNSET email: None | str | Unset = UNSET + reauth_password: None | str | Unset = UNSET + reauth_assertion: None | Unset | UpdateUserRequestReauthAssertionType0 = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: + from ..models.update_user_request_reauth_assertion_type_0 import ( + UpdateUserRequestReauthAssertionType0, + ) + name: None | str | Unset if isinstance(self.name, Unset): name = UNSET @@ -37,6 +56,20 @@ def to_dict(self) -> dict[str, Any]: else: email = self.email + reauth_password: None | str | Unset + if isinstance(self.reauth_password, Unset): + reauth_password = UNSET + else: + reauth_password = self.reauth_password + + reauth_assertion: dict[str, Any] | None | Unset + if isinstance(self.reauth_assertion, Unset): + reauth_assertion = UNSET + elif isinstance(self.reauth_assertion, UpdateUserRequestReauthAssertionType0): + reauth_assertion = self.reauth_assertion.to_dict() + else: + reauth_assertion = self.reauth_assertion + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update({}) @@ -44,11 +77,19 @@ def to_dict(self) -> dict[str, Any]: field_dict["name"] = name if email is not UNSET: field_dict["email"] = email + if reauth_password is not UNSET: + field_dict["reauth_password"] = reauth_password + if reauth_assertion is not UNSET: + field_dict["reauth_assertion"] = reauth_assertion return field_dict @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.update_user_request_reauth_assertion_type_0 import ( + UpdateUserRequestReauthAssertionType0, + ) + d = dict(src_dict) def _parse_name(data: object) -> None | str | Unset: @@ -69,9 +110,39 @@ def _parse_email(data: object) -> None | str | Unset: email = _parse_email(d.pop("email", UNSET)) + def _parse_reauth_password(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + reauth_password = _parse_reauth_password(d.pop("reauth_password", UNSET)) + + def _parse_reauth_assertion( + data: object, + ) -> None | Unset | UpdateUserRequestReauthAssertionType0: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + reauth_assertion_type_0 = UpdateUserRequestReauthAssertionType0.from_dict(data) + + return reauth_assertion_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(None | Unset | UpdateUserRequestReauthAssertionType0, data) + + reauth_assertion = _parse_reauth_assertion(d.pop("reauth_assertion", UNSET)) + update_user_request = cls( name=name, email=email, + reauth_password=reauth_password, + reauth_assertion=reauth_assertion, ) update_user_request.additional_properties = d diff --git a/robosystems_client/models/sec_connection_config.py b/robosystems_client/models/update_user_request_reauth_assertion_type_0.py similarity index 69% rename from robosystems_client/models/sec_connection_config.py rename to robosystems_client/models/update_user_request_reauth_assertion_type_0.py index 9b114ee..6092381 100644 --- a/robosystems_client/models/sec_connection_config.py +++ b/robosystems_client/models/update_user_request_reauth_assertion_type_0.py @@ -6,44 +6,29 @@ from attrs import define as _attrs_define from attrs import field as _attrs_field -T = TypeVar("T", bound="SECConnectionConfig") +T = TypeVar("T", bound="UpdateUserRequestReauthAssertionType0") @_attrs_define -class SECConnectionConfig: - """SEC-specific connection configuration. +class UpdateUserRequestReauthAssertionType0: + """ """ - Attributes: - cik (str): SEC Central Index Key - """ - - cik: str additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: - cik = self.cik field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update( - { - "cik": cik, - } - ) return field_dict @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) - cik = d.pop("cik") - - sec_connection_config = cls( - cik=cik, - ) + update_user_request_reauth_assertion_type_0 = cls() - sec_connection_config.additional_properties = d - return sec_connection_config + update_user_request_reauth_assertion_type_0.additional_properties = d + return update_user_request_reauth_assertion_type_0 @property def additional_keys(self) -> list[str]: