diff --git a/robosystems_client/api/robo_ledger_analytical_views/live_financial_statement.py b/robosystems_client/api/robo_ledger_analytical_views/live_financial_statement.py index 6318e946..d9da5088 100644 --- a/robosystems_client/api/robo_ledger_analytical_views/live_financial_statement.py +++ b/robosystems_client/api/robo_ledger_analytical_views/live_financial_statement.py @@ -118,9 +118,10 @@ def sync_detailed( Generate an ad-hoc financial statement directly from the tenant's OLTP ledger data using the active CoA→GAAP mapping. This is the authoritative source for RoboLedger entity graphs — no graph materialization required. One entity's books: `entity_id` names a subsidiary, omitted means the - group parent; `consolidated` on the parent combines every entity of the group at the rs-gaap - concepts, with no eliminations. Rejected on shared-repository graphs; those should use `financial- - statement-analysis` instead. + group parent. On the parent, `scope: combined` sums every member consolidated in full at the rs-gaap + concepts for the months each was a member, nothing eliminated, and `scope: consolidated` adds the + consolidation entity's entries — the eliminations and noncontrolling interest. Rejected on shared- + repository graphs; those should use `financial-statement-analysis` instead. **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. @@ -164,9 +165,10 @@ def sync( Generate an ad-hoc financial statement directly from the tenant's OLTP ledger data using the active CoA→GAAP mapping. This is the authoritative source for RoboLedger entity graphs — no graph materialization required. One entity's books: `entity_id` names a subsidiary, omitted means the - group parent; `consolidated` on the parent combines every entity of the group at the rs-gaap - concepts, with no eliminations. Rejected on shared-repository graphs; those should use `financial- - statement-analysis` instead. + group parent. On the parent, `scope: combined` sums every member consolidated in full at the rs-gaap + concepts for the months each was a member, nothing eliminated, and `scope: consolidated` adds the + consolidation entity's entries — the eliminations and noncontrolling interest. Rejected on shared- + repository graphs; those should use `financial-statement-analysis` instead. **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. @@ -205,9 +207,10 @@ async def asyncio_detailed( Generate an ad-hoc financial statement directly from the tenant's OLTP ledger data using the active CoA→GAAP mapping. This is the authoritative source for RoboLedger entity graphs — no graph materialization required. One entity's books: `entity_id` names a subsidiary, omitted means the - group parent; `consolidated` on the parent combines every entity of the group at the rs-gaap - concepts, with no eliminations. Rejected on shared-repository graphs; those should use `financial- - statement-analysis` instead. + group parent. On the parent, `scope: combined` sums every member consolidated in full at the rs-gaap + concepts for the months each was a member, nothing eliminated, and `scope: consolidated` adds the + consolidation entity's entries — the eliminations and noncontrolling interest. Rejected on shared- + repository graphs; those should use `financial-statement-analysis` instead. **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. @@ -249,9 +252,10 @@ async def asyncio( Generate an ad-hoc financial statement directly from the tenant's OLTP ledger data using the active CoA→GAAP mapping. This is the authoritative source for RoboLedger entity graphs — no graph materialization required. One entity's books: `entity_id` names a subsidiary, omitted means the - group parent; `consolidated` on the parent combines every entity of the group at the rs-gaap - concepts, with no eliminations. Rejected on shared-repository graphs; those should use `financial- - statement-analysis` instead. + group parent. On the parent, `scope: combined` sums every member consolidated in full at the rs-gaap + concepts for the months each was a member, nothing eliminated, and `scope: consolidated` adds the + consolidation entity's entries — the eliminations and noncontrolling interest. Rejected on shared- + repository graphs; those should use `financial-statement-analysis` instead. **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/robo_ledger_setup/create_entity.py b/robosystems_client/api/robo_ledger_setup/create_entity.py index b72c65dc..9f017d42 100644 --- a/robosystems_client/api/robo_ledger_setup/create_entity.py +++ b/robosystems_client/api/robo_ledger_setup/create_entity.py @@ -121,7 +121,10 @@ def sync_detailed( omitting it means the group parent. The Reporting Style follows `entity_type` unless `reporting_style_id` names one. `ticker` prefixes the entity's account names and must be unique in the graph (409). There is no cap on entities: a graph is one reporting group, and everyone with - access to it sees every entity. + access to it sees every entity. `ownership_pct` implies the `consolidation_method` (50 and above + full, 20 to 50 equity, below 20 cost) unless one is given; `entity_role: consolidation` makes this + the group's entity for consolidating entries, read by the consolidated statements only; `joined_on` + dates an acquired subsidiary's membership. **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. @@ -176,7 +179,10 @@ def sync( omitting it means the group parent. The Reporting Style follows `entity_type` unless `reporting_style_id` names one. `ticker` prefixes the entity's account names and must be unique in the graph (409). There is no cap on entities: a graph is one reporting group, and everyone with - access to it sees every entity. + access to it sees every entity. `ownership_pct` implies the `consolidation_method` (50 and above + full, 20 to 50 equity, below 20 cost) unless one is given; `entity_role: consolidation` makes this + the group's entity for consolidating entries, read by the consolidated statements only; `joined_on` + dates an acquired subsidiary's membership. **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. @@ -226,7 +232,10 @@ async def asyncio_detailed( omitting it means the group parent. The Reporting Style follows `entity_type` unless `reporting_style_id` names one. `ticker` prefixes the entity's account names and must be unique in the graph (409). There is no cap on entities: a graph is one reporting group, and everyone with - access to it sees every entity. + access to it sees every entity. `ownership_pct` implies the `consolidation_method` (50 and above + full, 20 to 50 equity, below 20 cost) unless one is given; `entity_role: consolidation` makes this + the group's entity for consolidating entries, read by the consolidated statements only; `joined_on` + dates an acquired subsidiary's membership. **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. @@ -279,7 +288,10 @@ async def asyncio( omitting it means the group parent. The Reporting Style follows `entity_type` unless `reporting_style_id` names one. `ticker` prefixes the entity's account names and must be unique in the graph (409). There is no cap on entities: a graph is one reporting group, and everyone with - access to it sees every entity. + access to it sees every entity. `ownership_pct` implies the `consolidation_method` (50 and above + full, 20 to 50 equity, below 20 cost) unless one is given; `entity_role: consolidation` makes this + the group's entity for consolidating entries, read by the consolidated statements only; `joined_on` + dates an acquired subsidiary's membership. **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/robo_ledger_setup/update_entity.py b/robosystems_client/api/robo_ledger_setup/update_entity.py index 1d9f8d37..b4882faa 100644 --- a/robosystems_client/api/robo_ledger_setup/update_entity.py +++ b/robosystems_client/api/robo_ledger_setup/update_entity.py @@ -116,6 +116,10 @@ def sync_detailed( Update an entity of the graph's reporting group. Only provided (non-null) fields are updated. Omit `entity_id` to target the group parent; name a subsidiary's id to edit it. `ownership_pct` is refused on the group parent (422), and `ticker` must stay unique in the graph (409). + `consolidation_method` overrides the treatment the share implies (a new share re-derives it unless + both are given), `entity_role: consolidation` marks the group's entity for consolidating entries, + and `joined_on` / `left_on` bound its membership by month — set `left_on` when a subsidiary leaves + the group and its history stays readable under it. **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. @@ -164,6 +168,10 @@ def sync( Update an entity of the graph's reporting group. Only provided (non-null) fields are updated. Omit `entity_id` to target the group parent; name a subsidiary's id to edit it. `ownership_pct` is refused on the group parent (422), and `ticker` must stay unique in the graph (409). + `consolidation_method` overrides the treatment the share implies (a new share re-derives it unless + both are given), `entity_role: consolidation` marks the group's entity for consolidating entries, + and `joined_on` / `left_on` bound its membership by month — set `left_on` when a subsidiary leaves + the group and its history stays readable under it. **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. @@ -207,6 +215,10 @@ async def asyncio_detailed( Update an entity of the graph's reporting group. Only provided (non-null) fields are updated. Omit `entity_id` to target the group parent; name a subsidiary's id to edit it. `ownership_pct` is refused on the group parent (422), and `ticker` must stay unique in the graph (409). + `consolidation_method` overrides the treatment the share implies (a new share re-derives it unless + both are given), `entity_role: consolidation` marks the group's entity for consolidating entries, + and `joined_on` / `left_on` bound its membership by month — set `left_on` when a subsidiary leaves + the group and its history stays readable under it. **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. @@ -253,6 +265,10 @@ async def asyncio( Update an entity of the graph's reporting group. Only provided (non-null) fields are updated. Omit `entity_id` to target the group parent; name a subsidiary's id to edit it. `ownership_pct` is refused on the group parent (422), and `ticker` must stay unique in the graph (409). + `consolidation_method` overrides the treatment the share implies (a new share re-derives it unless + both are given), `entity_role: consolidation` marks the group's entity for consolidating entries, + and `joined_on` / `left_on` bound its membership by month — set `left_on` when a subsidiary leaves + the group and its history stays readable under it. **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/robo_ledger_taxonomy_mapping/create_taxonomy_block.py b/robosystems_client/api/robo_ledger_taxonomy_mapping/create_taxonomy_block.py index 4fe66c02..5e04d078 100644 --- a/robosystems_client/api/robo_ledger_taxonomy_mapping/create_taxonomy_block.py +++ b/robosystems_client/api/robo_ledger_taxonomy_mapping/create_taxonomy_block.py @@ -117,10 +117,15 @@ def sync_detailed( elements, associations, and rules. Dispatches by `taxonomy_type` — `chart_of_accounts` (declarative 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'). + environment (TAXONOMY_AUTHORING_ENABLED) — disabled surfaces 403. A `reporting_extension` structure + with `extends_network` adds rows to the entity's balance sheet, income statement, cash flow or + equity statement: its arcs layer onto that Reporting Style network, anchored and checked when + authored (refused with a reason, 422). Prefer an rs-gaap concept for a row — any library concept may + be named, including ones not yet in this graph — and give a tenant concept a `parent_ref` to the rs- + gaap concept it refines. 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. @@ -172,10 +177,15 @@ def sync( elements, associations, and rules. Dispatches by `taxonomy_type` — `chart_of_accounts` (declarative 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'). + environment (TAXONOMY_AUTHORING_ENABLED) — disabled surfaces 403. A `reporting_extension` structure + with `extends_network` adds rows to the entity's balance sheet, income statement, cash flow or + equity statement: its arcs layer onto that Reporting Style network, anchored and checked when + authored (refused with a reason, 422). Prefer an rs-gaap concept for a row — any library concept may + be named, including ones not yet in this graph — and give a tenant concept a `parent_ref` to the rs- + gaap concept it refines. 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,10 +232,15 @@ async def asyncio_detailed( elements, associations, and rules. Dispatches by `taxonomy_type` — `chart_of_accounts` (declarative 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'). + environment (TAXONOMY_AUTHORING_ENABLED) — disabled surfaces 403. A `reporting_extension` structure + with `extends_network` adds rows to the entity's balance sheet, income statement, cash flow or + equity statement: its arcs layer onto that Reporting Style network, anchored and checked when + authored (refused with a reason, 422). Prefer an rs-gaap concept for a row — any library concept may + be named, including ones not yet in this graph — and give a tenant concept a `parent_ref` to the rs- + gaap concept it refines. 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. @@ -275,10 +290,15 @@ async def asyncio( elements, associations, and rules. Dispatches by `taxonomy_type` — `chart_of_accounts` (declarative 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'). + environment (TAXONOMY_AUTHORING_ENABLED) — disabled surfaces 403. A `reporting_extension` structure + with `extends_network` adds rows to the entity's balance sheet, income statement, cash flow or + equity statement: its arcs layer onto that Reporting Style network, anchored and checked when + authored (refused with a reason, 422). Prefer an rs-gaap concept for a row — any library concept may + be named, including ones not yet in this graph — and give a tenant concept a `parent_ref` to the rs- + gaap concept it refines. 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/graphql/generated/get_ledger_entity.py b/robosystems_client/graphql/generated/get_ledger_entity.py index 0f6eb4d5..fcbce8ea 100644 --- a/robosystems_client/graphql/generated/get_ledger_entity.py +++ b/robosystems_client/graphql/generated/get_ledger_entity.py @@ -33,6 +33,10 @@ class GetLedgerEntityEntity(BaseModel): is_parent: bool = Field(alias="isParent") parent_entity_id: Optional[str] = Field(alias="parentEntityId") ownership_pct: Optional[float] = Field(alias="ownershipPct") + consolidation_method: str = Field(alias="consolidationMethod") + entity_role: str = Field(alias="entityRole") + joined_on: Optional[str] = Field(alias="joinedOn") + left_on: Optional[str] = Field(alias="leftOn") source: str source_id: Optional[str] = Field(alias="sourceId") source_graph_id: Optional[str] = Field(alias="sourceGraphId") diff --git a/robosystems_client/graphql/generated/list_ledger_entities.py b/robosystems_client/graphql/generated/list_ledger_entities.py index 3a6483ca..17559b57 100644 --- a/robosystems_client/graphql/generated/list_ledger_entities.py +++ b/robosystems_client/graphql/generated/list_ledger_entities.py @@ -21,6 +21,10 @@ class ListLedgerEntitiesEntities(BaseModel): is_parent: bool = Field(alias="isParent") parent_entity_id: Optional[str] = Field(alias="parentEntityId") ownership_pct: Optional[float] = Field(alias="ownershipPct") + consolidation_method: str = Field(alias="consolidationMethod") + entity_role: str = Field(alias="entityRole") + joined_on: Optional[str] = Field(alias="joinedOn") + left_on: Optional[str] = Field(alias="leftOn") source: str source_graph_id: Optional[str] = Field(alias="sourceGraphId") connection_id: Optional[str] = Field(alias="connectionId") diff --git a/robosystems_client/graphql/generated/operations.py b/robosystems_client/graphql/generated/operations.py index 0fe48d2d..a2a3c4af 100644 --- a/robosystems_client/graphql/generated/operations.py +++ b/robosystems_client/graphql/generated/operations.py @@ -639,6 +639,10 @@ isParent parentEntityId ownershipPct + consolidationMethod + entityRole + joinedOn + leftOn source sourceId sourceGraphId @@ -1594,6 +1598,10 @@ isParent parentEntityId ownershipPct + consolidationMethod + entityRole + joinedOn + leftOn source sourceGraphId connectionId diff --git a/robosystems_client/graphql/operations/ledger/GetLedgerEntity.graphql b/robosystems_client/graphql/operations/ledger/GetLedgerEntity.graphql index 872ed709..392e307b 100644 --- a/robosystems_client/graphql/operations/ledger/GetLedgerEntity.graphql +++ b/robosystems_client/graphql/operations/ledger/GetLedgerEntity.graphql @@ -23,6 +23,10 @@ query GetLedgerEntity($entityId: String) { isParent parentEntityId ownershipPct + consolidationMethod + entityRole + joinedOn + leftOn source sourceId sourceGraphId diff --git a/robosystems_client/graphql/operations/ledger/ListLedgerEntities.graphql b/robosystems_client/graphql/operations/ledger/ListLedgerEntities.graphql index e6f0fabf..4a3cea38 100644 --- a/robosystems_client/graphql/operations/ledger/ListLedgerEntities.graphql +++ b/robosystems_client/graphql/operations/ledger/ListLedgerEntities.graphql @@ -11,6 +11,10 @@ query ListLedgerEntities($source: String) { isParent parentEntityId ownershipPct + consolidationMethod + entityRole + joinedOn + leftOn source sourceGraphId connectionId diff --git a/robosystems_client/graphql/schema.graphql b/robosystems_client/graphql/schema.graphql index 6524dab1..09c00ad9 100644 --- a/robosystems_client/graphql/schema.graphql +++ b/robosystems_client/graphql/schema.graphql @@ -1572,6 +1572,26 @@ type LedgerEntity { """ ownershipPct: Float + """ + How the group's consolidated statements treat this entity: `full` (its books are summed and an outside owner's share is carried as noncontrolling interest), `equity` (one investment line and one income line), `cost` (an investment at cost) or `none` (the group parent, the consolidation entity, a linked counterparty). Derived from `ownershipPct` when not given — 50 and above `full`, 20 to 50 `equity`, below 20 `cost`, unrecorded `full` — and set by a person where control is not the percentage: a managing member with a minority stake consolidates in full, a majority without control takes the equity method. + """ + consolidationMethod: String! + + """ + `operating` keeps a company's books. `consolidation` is the group's one entity for the consolidating entries — eliminations, noncontrolling interest, the equity-method pick-up — the adjustments column of a consolidation worksheet, which only the consolidated statements read and no operating company's statements ever include. Its method is `none`. + """ + entityRole: String! + + """ + The month this entity became a member of the group, as any date in it; null is a member since the beginning. The consolidated statements include it from that month. Membership is by month: a period column wider than a month that overlaps the interval is summed whole, so a member's books in this graph should hold only the months it belonged. + """ + joinedOn: Date + + """ + The month this entity left the group, as any date in it; null is a member still. The consolidated statements include it through that month and leave it out after. Membership is by month: a period column wider than a month that overlaps the interval is summed whole, so a member's books in this graph should hold only the months it belonged. + """ + leftOn: Date + """Provenance: 'native' | 'sec' | 'quickbooks' | 'xero' | 'plaid'.""" source: String! @@ -3996,10 +4016,15 @@ of its atoms. Read in one query, so a graph's whole catalogue lists in the time one envelope builds. """ type InformationBlockSummary { + """The block's structure id.""" id: String! """Discriminator — 'schedule', …""" blockType: String! + + """ + The block's own name — the instance ('FY27 Operating Budget'), where `displayName` is its type's label ('Forecast'). + """ name: String! """Registry-sourced display label (e.g., 'Schedule').""" diff --git a/robosystems_client/models/__init__.py b/robosystems_client/models/__init__.py index 6459d33e..1514cdbe 100644 --- a/robosystems_client/models/__init__.py +++ b/robosystems_client/models/__init__.py @@ -105,6 +105,10 @@ from .create_document_upload_op import CreateDocumentUploadOp from .create_document_upload_op_content_type import CreateDocumentUploadOpContentType from .create_entity_request import CreateEntityRequest +from .create_entity_request_consolidation_method_type_0 import ( + CreateEntityRequestConsolidationMethodType0, +) +from .create_entity_request_entity_role_type_0 import CreateEntityRequestEntityRoleType0 from .create_event_block_request import CreateEventBlockRequest from .create_event_block_request_event_action_type_0 import ( CreateEventBlockRequestEventActionType0, @@ -416,6 +420,9 @@ from .list_subgraphs_response import ListSubgraphsResponse from .list_table_files_response import ListTableFilesResponse from .live_financial_statement_request import LiveFinancialStatementRequest +from .live_financial_statement_request_scope_type_0 import ( + LiveFinancialStatementRequestScopeType0, +) from .live_financial_statement_response import LiveFinancialStatementResponse from .live_statement_fact_row import LiveStatementFactRow from .login_request import LoginRequest @@ -1089,6 +1096,10 @@ from .update_agent_request_metadata_patch import UpdateAgentRequestMetadataPatch from .update_api_key_request import UpdateAPIKeyRequest from .update_entity_request import UpdateEntityRequest +from .update_entity_request_consolidation_method_type_0 import ( + UpdateEntityRequestConsolidationMethodType0, +) +from .update_entity_request_entity_role_type_0 import UpdateEntityRequestEntityRoleType0 from .update_event_block_request import UpdateEventBlockRequest from .update_event_block_request_event_action_type_0 import ( UpdateEventBlockRequestEventActionType0, @@ -1253,6 +1264,8 @@ "CreateDocumentUploadOp", "CreateDocumentUploadOpContentType", "CreateEntityRequest", + "CreateEntityRequestConsolidationMethodType0", + "CreateEntityRequestEntityRoleType0", "CreateEventBlockRequest", "CreateEventBlockRequestEventActionType0", "CreateEventBlockRequestEventCategory", @@ -1494,6 +1507,7 @@ "ListSubgraphsResponse", "ListTableFilesResponse", "LiveFinancialStatementRequest", + "LiveFinancialStatementRequestScopeType0", "LiveFinancialStatementResponse", "LiveStatementFactRow", "LoginRequest", @@ -1889,6 +1903,8 @@ "UpdateAgentRequestMetadataPatch", "UpdateAPIKeyRequest", "UpdateEntityRequest", + "UpdateEntityRequestConsolidationMethodType0", + "UpdateEntityRequestEntityRoleType0", "UpdateEventBlockRequest", "UpdateEventBlockRequestEventActionType0", "UpdateEventBlockRequestMetadataPatch", diff --git a/robosystems_client/models/create_entity_request.py b/robosystems_client/models/create_entity_request.py index d99d2cf8..57ac7503 100644 --- a/robosystems_client/models/create_entity_request.py +++ b/robosystems_client/models/create_entity_request.py @@ -1,11 +1,18 @@ 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 ..models.create_entity_request_consolidation_method_type_0 import ( + CreateEntityRequestConsolidationMethodType0, +) +from ..models.create_entity_request_entity_role_type_0 import ( + CreateEntityRequestEntityRoleType0, +) from ..types import UNSET, Unset T = TypeVar("T", bound="CreateEntityRequest") @@ -34,6 +41,25 @@ class CreateEntityRequest: subsidiary to nest a sub-group under it. ownership_pct (float | None | Unset): The parent's share of this entity, as a percent (100 = wholly owned). Omit when not recorded. Refused on a graph's first entity, which becomes the group parent. + consolidation_method (CreateEntityRequestConsolidationMethodType0 | None | Unset): How the group's consolidated + statements treat this entity: `full` (its books are summed and an outside owner's share is carried as + noncontrolling interest), `equity` (one investment line and one income line), `cost` (an investment at cost) or + `none` (the group parent, the consolidation entity, a linked counterparty). Derived from `ownership_pct` when + not given — 50 and above `full`, 20 to 50 `equity`, below 20 `cost`, unrecorded `full` — and set by a person + where control is not the percentage: a managing member with a minority stake consolidates in full, a majority + without control takes the equity method. Omit to derive it; a graph's first entity and a `consolidation` entity + take `none`. + entity_role (CreateEntityRequestEntityRoleType0 | None | Unset): `operating` keeps a company's books. + `consolidation` is the group's one entity for the consolidating entries — eliminations, noncontrolling interest, + the equity-method pick-up — the adjustments column of a consolidation worksheet, which only the consolidated + statements read and no operating company's statements ever include. Its method is `none`. Default `operating`; a + graph's first entity, its group parent, is always operating. Start a consolidation entity's chart from the + `consolidation` template. + joined_on (datetime.date | None | Unset): The month this entity became a member of the group, as any date in it; + null is a member since the beginning. The consolidated statements include it from that month. Membership is by + month: a period column wider than a month that overlaps the interval is summed whole, so a member's books in + this graph should hold only the months it belonged. Omit for a subsidiary formed by the parent; give the + acquisition month for one acquired, whose books in this graph then hold only what follows it. ticker (None | str | Unset): Short symbol, unique in the graph; it prefixes the entity's account names (`coa-:1000`). Derived from the name's initials when omitted. uri (None | str | Unset): Canonical URL / external identifier. @@ -62,6 +88,11 @@ class CreateEntityRequest: reporting_style_id: None | str | Unset = UNSET parent_entity_id: None | str | Unset = UNSET ownership_pct: float | None | Unset = UNSET + consolidation_method: CreateEntityRequestConsolidationMethodType0 | None | Unset = ( + UNSET + ) + entity_role: CreateEntityRequestEntityRoleType0 | None | Unset = UNSET + joined_on: datetime.date | None | Unset = UNSET ticker: None | str | Unset = UNSET uri: None | str | Unset = UNSET cik: None | str | Unset = UNSET @@ -115,6 +146,32 @@ def to_dict(self) -> dict[str, Any]: else: ownership_pct = self.ownership_pct + consolidation_method: None | str | Unset + if isinstance(self.consolidation_method, Unset): + consolidation_method = UNSET + elif isinstance( + self.consolidation_method, CreateEntityRequestConsolidationMethodType0 + ): + consolidation_method = self.consolidation_method.value + else: + consolidation_method = self.consolidation_method + + entity_role: None | str | Unset + if isinstance(self.entity_role, Unset): + entity_role = UNSET + elif isinstance(self.entity_role, CreateEntityRequestEntityRoleType0): + entity_role = self.entity_role.value + else: + entity_role = self.entity_role + + joined_on: None | str | Unset + if isinstance(self.joined_on, Unset): + joined_on = UNSET + elif isinstance(self.joined_on, datetime.date): + joined_on = self.joined_on.isoformat() + else: + joined_on = self.joined_on + ticker: None | str | Unset if isinstance(self.ticker, Unset): ticker = UNSET @@ -240,6 +297,12 @@ def to_dict(self) -> dict[str, Any]: field_dict["parent_entity_id"] = parent_entity_id if ownership_pct is not UNSET: field_dict["ownership_pct"] = ownership_pct + if consolidation_method is not UNSET: + field_dict["consolidation_method"] = consolidation_method + if entity_role is not UNSET: + field_dict["entity_role"] = entity_role + if joined_on is not UNSET: + field_dict["joined_on"] = joined_on if ticker is not UNSET: field_dict["ticker"] = ticker if uri is not UNSET: @@ -329,6 +392,63 @@ def _parse_ownership_pct(data: object) -> float | None | Unset: ownership_pct = _parse_ownership_pct(d.pop("ownership_pct", UNSET)) + def _parse_consolidation_method( + data: object, + ) -> CreateEntityRequestConsolidationMethodType0 | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + consolidation_method_type_0 = CreateEntityRequestConsolidationMethodType0(data) + + return consolidation_method_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(CreateEntityRequestConsolidationMethodType0 | None | Unset, data) + + consolidation_method = _parse_consolidation_method( + d.pop("consolidation_method", UNSET) + ) + + def _parse_entity_role( + data: object, + ) -> CreateEntityRequestEntityRoleType0 | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + entity_role_type_0 = CreateEntityRequestEntityRoleType0(data) + + return entity_role_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(CreateEntityRequestEntityRoleType0 | None | Unset, data) + + entity_role = _parse_entity_role(d.pop("entity_role", UNSET)) + + def _parse_joined_on(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() + joined_on_type_0 = datetime.date.fromisoformat(data) + + return joined_on_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.date | None | Unset, data) + + joined_on = _parse_joined_on(d.pop("joined_on", UNSET)) + def _parse_ticker(data: object) -> None | str | Unset: if data is None: return data @@ -502,6 +622,9 @@ def _parse_address_country(data: object) -> None | str | Unset: reporting_style_id=reporting_style_id, parent_entity_id=parent_entity_id, ownership_pct=ownership_pct, + consolidation_method=consolidation_method, + entity_role=entity_role, + joined_on=joined_on, ticker=ticker, uri=uri, cik=cik, diff --git a/robosystems_client/models/create_entity_request_consolidation_method_type_0.py b/robosystems_client/models/create_entity_request_consolidation_method_type_0.py new file mode 100644 index 00000000..5decc44e --- /dev/null +++ b/robosystems_client/models/create_entity_request_consolidation_method_type_0.py @@ -0,0 +1,11 @@ +from enum import Enum + + +class CreateEntityRequestConsolidationMethodType0(str, Enum): + COST = "cost" + EQUITY = "equity" + FULL = "full" + NONE = "none" + + def __str__(self) -> str: + return str(self.value) diff --git a/robosystems_client/models/create_entity_request_entity_role_type_0.py b/robosystems_client/models/create_entity_request_entity_role_type_0.py new file mode 100644 index 00000000..b328994e --- /dev/null +++ b/robosystems_client/models/create_entity_request_entity_role_type_0.py @@ -0,0 +1,9 @@ +from enum import Enum + + +class CreateEntityRequestEntityRoleType0(str, Enum): + CONSOLIDATION = "consolidation" + OPERATING = "operating" + + def __str__(self) -> str: + return str(self.value) diff --git a/robosystems_client/models/initialize_chart_of_accounts_request.py b/robosystems_client/models/initialize_chart_of_accounts_request.py index 061e6f41..398fb956 100644 --- a/robosystems_client/models/initialize_chart_of_accounts_request.py +++ b/robosystems_client/models/initialize_chart_of_accounts_request.py @@ -28,7 +28,9 @@ class InitializeChartOfAccountsRequest: Attributes: template (InitializeChartOfAccountsRequestTemplate): Template key: `saas` (subscription software — deferred revenue, cost of revenue, R&D / S&M / G&A), `services` (professional services — no inventory, no COGS), - `product` (inventory and cost of goods sold, direct + wholesale + subscription revenue). + `product` (inventory and cost of goods sold, direct + wholesale + subscription revenue), `consolidation` (a + group's consolidation entity: the eliminated investment, intercompany and subsidiary-equity rows, noncontrolling + interest and its share of income — the adjustments column, never an operating company's chart). entity_id (None | str | Unset): The entity to give a chart to, by id. Omit for the group parent. A sibling already having one is no bar. entity_type (None | str | Unset): Legal form for the equity mapping: `corporation`, `llc` or `partnership`. diff --git a/robosystems_client/models/initialize_chart_of_accounts_request_template.py b/robosystems_client/models/initialize_chart_of_accounts_request_template.py index b85f0c45..07a78cdc 100644 --- a/robosystems_client/models/initialize_chart_of_accounts_request_template.py +++ b/robosystems_client/models/initialize_chart_of_accounts_request_template.py @@ -2,6 +2,7 @@ class InitializeChartOfAccountsRequestTemplate(str, Enum): + CONSOLIDATION = "consolidation" PRODUCT = "product" SAAS = "saas" SERVICES = "services" diff --git a/robosystems_client/models/initialize_chart_of_accounts_response_template.py b/robosystems_client/models/initialize_chart_of_accounts_response_template.py index d01577c8..dae6872e 100644 --- a/robosystems_client/models/initialize_chart_of_accounts_response_template.py +++ b/robosystems_client/models/initialize_chart_of_accounts_response_template.py @@ -2,6 +2,7 @@ class InitializeChartOfAccountsResponseTemplate(str, Enum): + CONSOLIDATION = "consolidation" PRODUCT = "product" SAAS = "saas" SERVICES = "services" diff --git a/robosystems_client/models/journal_entry_line_item_input.py b/robosystems_client/models/journal_entry_line_item_input.py index 9f89946d..4e015079 100644 --- a/robosystems_client/models/journal_entry_line_item_input.py +++ b/robosystems_client/models/journal_entry_line_item_input.py @@ -33,7 +33,9 @@ class JournalEntryLineItemInput: (`flowCandidates(entityId)` lists the rows this company's statement offers). Only for a loan drawn or repaid, capital put in or taken out, an asset bought or sold; omitted, the account's default flow applies. A flow set on one side of the entry tags the untagged lines on the other: the cash flow statement reads the cash line and the - roll-forwards read the account line. Refused when it is not a row of the entity's cash flow statement. + roll-forwards read the account line. On the group's consolidation entity, which moves no cash, every tagged line + counts on its own, cash-effect signed (a credit is an inflow), so an elimination offsets the flow a member's + line produced. Refused when it is not a row of the entity's cash flow statement. metadata (JournalEntryLineItemInputMetadataType0 | None | Unset): Optional per-line metadata stamped on `LineItem.metadata_`. Used to carry source-system fields the standard columns don't cover — e.g. an external flow-tag code that drives rollforward attribution (`transaction_description_code`), an external memo, or a cost- diff --git a/robosystems_client/models/ledger_entity_response.py b/robosystems_client/models/ledger_entity_response.py index b76f6176..5c45c117 100644 --- a/robosystems_client/models/ledger_entity_response.py +++ b/robosystems_client/models/ledger_entity_response.py @@ -1,5 +1,6 @@ from __future__ import annotations +import datetime from collections.abc import Mapping from typing import Any, TypeVar, cast @@ -47,6 +48,24 @@ class LedgerEntityResponse: parent_entity_id (None | str | Unset): Parent entity ID for subsidiaries; null for top-level. ownership_pct (float | None | Unset): The parent's share of this entity, as a percent (100 = wholly owned). Null on the group parent, and where it was never recorded. + consolidation_method (str | Unset): How the group's consolidated statements treat this entity: `full` (its books + are summed and an outside owner's share is carried as noncontrolling interest), `equity` (one investment line + and one income line), `cost` (an investment at cost) or `none` (the group parent, the consolidation entity, a + linked counterparty). Derived from `ownership_pct` when not given — 50 and above `full`, 20 to 50 `equity`, + below 20 `cost`, unrecorded `full` — and set by a person where control is not the percentage: a managing member + with a minority stake consolidates in full, a majority without control takes the equity method. Default: 'none'. + entity_role (str | Unset): `operating` keeps a company's books. `consolidation` is the group's one entity for + the consolidating entries — eliminations, noncontrolling interest, the equity-method pick-up — the adjustments + column of a consolidation worksheet, which only the consolidated statements read and no operating company's + statements ever include. Its method is `none`. Default: 'operating'. + joined_on (datetime.date | None | Unset): The month this entity became a member of the group, as any date in it; + null is a member since the beginning. The consolidated statements include it from that month. Membership is by + month: a period column wider than a month that overlaps the interval is summed whole, so a member's books in + this graph should hold only the months it belonged. + left_on (datetime.date | None | Unset): The month this entity left the group, as any date in it; null is a + member still. The consolidated statements include it through that month and leave it out after. Membership is by + month: a period column wider than a month that overlaps the interval is summed whole, so a member's books in + this graph should hold only the months it belonged. source (str | Unset): Provenance: 'native' | 'sec' | 'quickbooks' | 'xero' | 'plaid'. Default: 'native'. source_id (None | str | Unset): Source-system primary key for sync reconciliation. source_graph_id (None | str | Unset): Origin graph for received entities (cross-graph linking, e.g. RoboInvestor @@ -84,6 +103,10 @@ class LedgerEntityResponse: is_parent: bool | Unset = True parent_entity_id: None | str | Unset = UNSET ownership_pct: float | None | Unset = UNSET + consolidation_method: str | Unset = "none" + entity_role: str | Unset = "operating" + joined_on: datetime.date | None | Unset = UNSET + left_on: datetime.date | None | Unset = UNSET source: str | Unset = "native" source_id: None | str | Unset = UNSET source_graph_id: None | str | Unset = UNSET @@ -220,6 +243,26 @@ def to_dict(self) -> dict[str, Any]: else: ownership_pct = self.ownership_pct + consolidation_method = self.consolidation_method + + entity_role = self.entity_role + + joined_on: None | str | Unset + if isinstance(self.joined_on, Unset): + joined_on = UNSET + elif isinstance(self.joined_on, datetime.date): + joined_on = self.joined_on.isoformat() + else: + joined_on = self.joined_on + + left_on: None | str | Unset + if isinstance(self.left_on, Unset): + left_on = UNSET + elif isinstance(self.left_on, datetime.date): + left_on = self.left_on.isoformat() + else: + left_on = self.left_on + source = self.source source_id: None | str | Unset @@ -332,6 +375,14 @@ def to_dict(self) -> dict[str, Any]: field_dict["parent_entity_id"] = parent_entity_id if ownership_pct is not UNSET: field_dict["ownership_pct"] = ownership_pct + if consolidation_method is not UNSET: + field_dict["consolidation_method"] = consolidation_method + if entity_role is not UNSET: + field_dict["entity_role"] = entity_role + if joined_on is not UNSET: + field_dict["joined_on"] = joined_on + if left_on is not UNSET: + field_dict["left_on"] = left_on if source is not UNSET: field_dict["source"] = source if source_id is not UNSET: @@ -541,6 +592,44 @@ def _parse_ownership_pct(data: object) -> float | None | Unset: ownership_pct = _parse_ownership_pct(d.pop("ownership_pct", UNSET)) + consolidation_method = d.pop("consolidation_method", UNSET) + + entity_role = d.pop("entity_role", UNSET) + + def _parse_joined_on(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() + joined_on_type_0 = datetime.date.fromisoformat(data) + + return joined_on_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.date | None | Unset, data) + + joined_on = _parse_joined_on(d.pop("joined_on", UNSET)) + + def _parse_left_on(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() + left_on_type_0 = datetime.date.fromisoformat(data) + + return left_on_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.date | None | Unset, data) + + left_on = _parse_left_on(d.pop("left_on", UNSET)) + source = d.pop("source", UNSET) def _parse_source_id(data: object) -> None | str | Unset: @@ -659,6 +748,10 @@ def _parse_updated_at(data: object) -> None | str | Unset: is_parent=is_parent, parent_entity_id=parent_entity_id, ownership_pct=ownership_pct, + consolidation_method=consolidation_method, + entity_role=entity_role, + joined_on=joined_on, + left_on=left_on, source=source, source_id=source_id, source_graph_id=source_graph_id, diff --git a/robosystems_client/models/live_financial_statement_request.py b/robosystems_client/models/live_financial_statement_request.py index 86bb865a..e70ef3e0 100644 --- a/robosystems_client/models/live_financial_statement_request.py +++ b/robosystems_client/models/live_financial_statement_request.py @@ -7,6 +7,9 @@ from attrs import define as _attrs_define from attrs import field as _attrs_field +from ..models.live_financial_statement_request_scope_type_0 import ( + LiveFinancialStatementRequestScopeType0, +) from ..types import UNSET, Unset T = TypeVar("T", bound="LiveFinancialStatementRequest") @@ -26,10 +29,16 @@ class LiveFinancialStatementRequest: period_end (datetime.date | None | Unset): Explicit window end. Overrides period_type/fiscal_year. period_type (None | str | Unset): annual | quarterly | instant (ignored when dates supplied) fiscal_year (int | None | Unset): Fiscal year for annual window (anchored on FiscalCalendar) - consolidated (bool | Unset): A combined statement, not a consolidation: every entity of the reporting group - rendered under the group parent's Reporting Style and summed per rs-gaap concept, with nothing eliminated - between them. Only on the group parent (422 on a subsidiary). An entity with no CoA mapping yet contributes - nothing and is left out of `combined_entity_ids`. Default: False. + scope (LiveFinancialStatementRequestScopeType0 | None | Unset): `entity` (the default): one entity's own books. + `combined`: on the group parent, every member consolidated in full rendered under the parent's Reporting Style + and summed per rs-gaap concept, each for the months it was a member — the pre-adjustment total, nothing + eliminated. `consolidated`: the same sum plus the consolidation entity, whose eliminations and noncontrolling + interest are the adjustments column, so a group that posts its consolidating entries there reads its + consolidated statement. An equity-method or cost member is never summed (its `consolidation_method` says so). + Both group scopes are read on the group parent only (422 on a subsidiary). An entity with no CoA mapping yet + contributes nothing and is left out of `combined_entity_ids`. + consolidated (bool | Unset): The older spelling of `scope: consolidated`, kept for callers that pass it; `scope` + wins when both are given. Default: False. limit (int | Unset): Max fact rows returned. Defaults to the ceiling so a statement is never cut mid-section — visible rows would stop footing to visible subtotals. Lower it only for a preview. Default: 1000. """ @@ -40,6 +49,7 @@ class LiveFinancialStatementRequest: period_end: datetime.date | None | Unset = UNSET period_type: None | str | Unset = UNSET fiscal_year: int | None | Unset = UNSET + scope: LiveFinancialStatementRequestScopeType0 | None | Unset = UNSET consolidated: bool | Unset = False limit: int | Unset = 1000 additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -81,6 +91,14 @@ def to_dict(self) -> dict[str, Any]: else: fiscal_year = self.fiscal_year + scope: None | str | Unset + if isinstance(self.scope, Unset): + scope = UNSET + elif isinstance(self.scope, LiveFinancialStatementRequestScopeType0): + scope = self.scope.value + else: + scope = self.scope + consolidated = self.consolidated limit = self.limit @@ -102,6 +120,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["period_type"] = period_type if fiscal_year is not UNSET: field_dict["fiscal_year"] = fiscal_year + if scope is not UNSET: + field_dict["scope"] = scope if consolidated is not UNSET: field_dict["consolidated"] = consolidated if limit is not UNSET: @@ -175,6 +195,25 @@ def _parse_fiscal_year(data: object) -> int | None | Unset: fiscal_year = _parse_fiscal_year(d.pop("fiscal_year", UNSET)) + def _parse_scope( + data: object, + ) -> LiveFinancialStatementRequestScopeType0 | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + scope_type_0 = LiveFinancialStatementRequestScopeType0(data) + + return scope_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(LiveFinancialStatementRequestScopeType0 | None | Unset, data) + + scope = _parse_scope(d.pop("scope", UNSET)) + consolidated = d.pop("consolidated", UNSET) limit = d.pop("limit", UNSET) @@ -186,6 +225,7 @@ def _parse_fiscal_year(data: object) -> int | None | Unset: period_end=period_end, period_type=period_type, fiscal_year=fiscal_year, + scope=scope, consolidated=consolidated, limit=limit, ) diff --git a/robosystems_client/models/live_financial_statement_request_scope_type_0.py b/robosystems_client/models/live_financial_statement_request_scope_type_0.py new file mode 100644 index 00000000..27899d07 --- /dev/null +++ b/robosystems_client/models/live_financial_statement_request_scope_type_0.py @@ -0,0 +1,10 @@ +from enum import Enum + + +class LiveFinancialStatementRequestScopeType0(str, Enum): + COMBINED = "combined" + CONSOLIDATED = "consolidated" + ENTITY = "entity" + + def __str__(self) -> str: + return str(self.value) diff --git a/robosystems_client/models/live_financial_statement_response.py b/robosystems_client/models/live_financial_statement_response.py index 0fbbe232..e47aa2d9 100644 --- a/robosystems_client/models/live_financial_statement_response.py +++ b/robosystems_client/models/live_financial_statement_response.py @@ -30,9 +30,12 @@ class LiveFinancialStatementResponse: facts (list[LiveStatementFactRow]): fact_count (int): entity_id (None | str | Unset): The entity whose books were rendered. - consolidated (bool | Unset): Whether the group's entities were summed into this: a combined statement, not a - consolidation — nothing is eliminated between them. Default: False. - combined_entity_ids (list[str] | Unset): The entities summed into a combined statement, parent first. + scope (str | Unset): What was rendered: `entity`, `combined` (the members summed, nothing eliminated) or + `consolidated` (the members plus the consolidation entity's adjustments). Default: 'entity'. + consolidated (bool | Unset): Whether the group's entities were summed into this — true for the `combined` and + `consolidated` scopes. Default: False. + combined_entity_ids (list[str] | Unset): The entities summed, parent first; on `consolidated` the consolidation + entity comes last. validation (None | Unset | ValidationCheckResponse): Guard-rail outcome for the rendered columns — accounting equation, net-income equation, totals footing, operating-plug size. Null only when no structure rendered. unmapped_count (int | Unset): Default: 0. @@ -45,6 +48,7 @@ class LiveFinancialStatementResponse: facts: list[LiveStatementFactRow] fact_count: int entity_id: None | str | Unset = UNSET + scope: str | Unset = "entity" consolidated: bool | Unset = False combined_entity_ids: list[str] | Unset = UNSET validation: None | Unset | ValidationCheckResponse = UNSET @@ -77,6 +81,8 @@ def to_dict(self) -> dict[str, Any]: else: entity_id = self.entity_id + scope = self.scope + consolidated = self.consolidated combined_entity_ids: list[str] | Unset = UNSET @@ -108,6 +114,8 @@ def to_dict(self) -> dict[str, Any]: ) if entity_id is not UNSET: field_dict["entity_id"] = entity_id + if scope is not UNSET: + field_dict["scope"] = scope if consolidated is not UNSET: field_dict["consolidated"] = consolidated if combined_entity_ids is not UNSET: @@ -157,6 +165,8 @@ def _parse_entity_id(data: object) -> None | str | Unset: entity_id = _parse_entity_id(d.pop("entity_id", UNSET)) + scope = d.pop("scope", UNSET) + consolidated = d.pop("consolidated", UNSET) combined_entity_ids = cast(list[str], d.pop("combined_entity_ids", UNSET)) @@ -189,6 +199,7 @@ def _parse_validation(data: object) -> None | Unset | ValidationCheckResponse: facts=facts, fact_count=fact_count, entity_id=entity_id, + scope=scope, consolidated=consolidated, combined_entity_ids=combined_entity_ids, validation=validation, diff --git a/robosystems_client/models/live_statement_fact_row.py b/robosystems_client/models/live_statement_fact_row.py index fe7281b4..2a975efd 100644 --- a/robosystems_client/models/live_statement_fact_row.py +++ b/robosystems_client/models/live_statement_fact_row.py @@ -22,6 +22,8 @@ class LiveStatementFactRow: trait (None | str | Unset): depth (int | Unset): Default: 0. is_subtotal (bool | Unset): Default: False. + period_role (None | str | Unset): On the equity roll-forward, `start` for the beginning-balance row and `end` + for the ending-balance row. Null elsewhere. """ qname: str @@ -30,6 +32,7 @@ class LiveStatementFactRow: trait: None | str | Unset = UNSET depth: int | Unset = 0 is_subtotal: bool | Unset = False + period_role: None | str | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: @@ -53,6 +56,12 @@ def to_dict(self) -> dict[str, Any]: is_subtotal = self.is_subtotal + period_role: None | str | Unset + if isinstance(self.period_role, Unset): + period_role = UNSET + else: + period_role = self.period_role + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -68,6 +77,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["depth"] = depth if is_subtotal is not UNSET: field_dict["is_subtotal"] = is_subtotal + if period_role is not UNSET: + field_dict["period_role"] = period_role return field_dict @@ -104,6 +115,15 @@ def _parse_trait(data: object) -> None | str | Unset: is_subtotal = d.pop("is_subtotal", UNSET) + def _parse_period_role(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + period_role = _parse_period_role(d.pop("period_role", UNSET)) + live_statement_fact_row = cls( qname=qname, name=name, @@ -111,6 +131,7 @@ def _parse_trait(data: object) -> None | str | Unset: trait=trait, depth=depth, is_subtotal=is_subtotal, + period_role=period_role, ) live_statement_fact_row.additional_properties = d diff --git a/robosystems_client/models/taxonomy_block_structure_request.py b/robosystems_client/models/taxonomy_block_structure_request.py index 13ef89f2..dbe52527 100644 --- a/robosystems_client/models/taxonomy_block_structure_request.py +++ b/robosystems_client/models/taxonomy_block_structure_request.py @@ -39,6 +39,14 @@ class TaxonomyBlockStructureRequest: role_uri (None | str | Unset): target_framework (None | str | Unset): `coa_mapping` only: the framework this mapping maps the chart into, e.g. `rs-gaap`. Omitted means the graph's book framework. A chart holds one mapping per framework. + extends_network (None | str | Unset): `reporting_extension` only: the role URI of the Reporting Style network + this structure extends (e.g. `https://robosystems.ai/seattle/cm-roles/roles/rs-gaap-presentation/CashFlow- + indirect`). Its arcs then render as rows of that statement for every entity whose Style composes it. + `block_type` must be that network's statement type. A row's parent must be on the network, a balance sheet, + income statement or cash flow row needs a calculation arc from its section subtotal, an equity movement hangs + from the roll-forward's root, and a tenant concept placed as a row must set `parent_ref` to the rs-gaap concept + it refines — prefer the rs-gaap concept itself (any library concept may be named, including ones not yet in this + graph). metadata (TaxonomyBlockStructureRequestMetadata | Unset): """ @@ -50,6 +58,7 @@ class TaxonomyBlockStructureRequest: description: None | str | Unset = UNSET role_uri: None | str | Unset = UNSET target_framework: None | str | Unset = UNSET + extends_network: None | str | Unset = UNSET metadata: TaxonomyBlockStructureRequestMetadata | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -86,6 +95,12 @@ def to_dict(self) -> dict[str, Any]: else: target_framework = self.target_framework + extends_network: None | str | Unset + if isinstance(self.extends_network, Unset): + extends_network = UNSET + else: + extends_network = self.extends_network + metadata: dict[str, Any] | Unset = UNSET if not isinstance(self.metadata, Unset): metadata = self.metadata.to_dict() @@ -106,6 +121,8 @@ def to_dict(self) -> dict[str, Any]: field_dict["role_uri"] = role_uri if target_framework is not UNSET: field_dict["target_framework"] = target_framework + if extends_network is not UNSET: + field_dict["extends_network"] = extends_network if metadata is not UNSET: field_dict["metadata"] = metadata @@ -174,6 +191,15 @@ def _parse_target_framework(data: object) -> None | str | Unset: target_framework = _parse_target_framework(d.pop("target_framework", UNSET)) + def _parse_extends_network(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + extends_network = _parse_extends_network(d.pop("extends_network", UNSET)) + _metadata = d.pop("metadata", UNSET) metadata: TaxonomyBlockStructureRequestMetadata | Unset if isinstance(_metadata, Unset): @@ -188,6 +214,7 @@ def _parse_target_framework(data: object) -> None | str | Unset: description=description, role_uri=role_uri, target_framework=target_framework, + extends_network=extends_network, metadata=metadata, ) diff --git a/robosystems_client/models/update_entity_request.py b/robosystems_client/models/update_entity_request.py index 4111d88b..098867f7 100644 --- a/robosystems_client/models/update_entity_request.py +++ b/robosystems_client/models/update_entity_request.py @@ -1,11 +1,18 @@ 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 ..models.update_entity_request_consolidation_method_type_0 import ( + UpdateEntityRequestConsolidationMethodType0, +) +from ..models.update_entity_request_entity_role_type_0 import ( + UpdateEntityRequestEntityRoleType0, +) from ..types import UNSET, Unset T = TypeVar("T", bound="UpdateEntityRequest") @@ -46,7 +53,29 @@ class UpdateEntityRequest: address_postal_code (None | str | Unset): address_country (None | str | Unset): ownership_pct (float | None | Unset): The parent's share of this entity, as a percent. Refused on the group - parent, which has no owner in the graph. + parent, which has no owner in the graph. A new share re-derives `consolidation_method` unless that is given too. + consolidation_method (None | Unset | UpdateEntityRequestConsolidationMethodType0): How the group's consolidated + statements treat this entity: `full` (its books are summed and an outside owner's share is carried as + noncontrolling interest), `equity` (one investment line and one income line), `cost` (an investment at cost) or + `none` (the group parent, the consolidation entity, a linked counterparty). Derived from `ownership_pct` when + not given — 50 and above `full`, 20 to 50 `equity`, below 20 `cost`, unrecorded `full` — and set by a person + where control is not the percentage: a managing member with a minority stake consolidates in full, a majority + without control takes the equity method. On the group parent and the consolidation entity only `none` holds. + entity_role (None | Unset | UpdateEntityRequestEntityRoleType0): `operating` keeps a company's books. + `consolidation` is the group's one entity for the consolidating entries — eliminations, noncontrolling interest, + the equity-method pick-up — the adjustments column of a consolidation worksheet, which only the consolidated + statements read and no operating company's statements ever include. Its method is `none`. Refused on the group + parent. Marking an entity `consolidation` sets its method to `none`. + joined_on (datetime.date | None | Unset): The month this entity became a member of the group, as any date in it; + null is a member since the beginning. The consolidated statements include it from that month. Membership is by + month: a period column wider than a month that overlaps the interval is summed whole, so a member's books in + this graph should hold only the months it belonged. Pass null to clear it. + left_on (datetime.date | None | Unset): The month this entity left the group, as any date in it; null is a + member still. The consolidated statements include it through that month and leave it out after. Membership is by + month: a period column wider than a month that overlaps the interval is summed whole, so a member's books in + this graph should hold only the months it belonged. Must not precede `joined_on`. Set it when a subsidiary is + sold, dissolved or deconsolidated; its closed months and stamped statements stay readable under the group. Pass + null to reopen membership. """ entity_id: None | str | Unset = UNSET @@ -73,6 +102,12 @@ class UpdateEntityRequest: address_postal_code: None | str | Unset = UNSET address_country: None | str | Unset = UNSET ownership_pct: float | None | Unset = UNSET + consolidation_method: None | Unset | UpdateEntityRequestConsolidationMethodType0 = ( + UNSET + ) + entity_role: None | Unset | UpdateEntityRequestEntityRoleType0 = UNSET + joined_on: datetime.date | None | Unset = UNSET + left_on: datetime.date | None | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: @@ -220,6 +255,40 @@ def to_dict(self) -> dict[str, Any]: else: ownership_pct = self.ownership_pct + consolidation_method: None | str | Unset + if isinstance(self.consolidation_method, Unset): + consolidation_method = UNSET + elif isinstance( + self.consolidation_method, UpdateEntityRequestConsolidationMethodType0 + ): + consolidation_method = self.consolidation_method.value + else: + consolidation_method = self.consolidation_method + + entity_role: None | str | Unset + if isinstance(self.entity_role, Unset): + entity_role = UNSET + elif isinstance(self.entity_role, UpdateEntityRequestEntityRoleType0): + entity_role = self.entity_role.value + else: + entity_role = self.entity_role + + joined_on: None | str | Unset + if isinstance(self.joined_on, Unset): + joined_on = UNSET + elif isinstance(self.joined_on, datetime.date): + joined_on = self.joined_on.isoformat() + else: + joined_on = self.joined_on + + left_on: None | str | Unset + if isinstance(self.left_on, Unset): + left_on = UNSET + elif isinstance(self.left_on, datetime.date): + left_on = self.left_on.isoformat() + else: + left_on = self.left_on + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update({}) @@ -271,6 +340,14 @@ def to_dict(self) -> dict[str, Any]: field_dict["address_country"] = address_country if ownership_pct is not UNSET: field_dict["ownership_pct"] = ownership_pct + if consolidation_method is not UNSET: + field_dict["consolidation_method"] = consolidation_method + if entity_role is not UNSET: + field_dict["entity_role"] = entity_role + if joined_on is not UNSET: + field_dict["joined_on"] = joined_on + if left_on is not UNSET: + field_dict["left_on"] = left_on return field_dict @@ -498,6 +575,80 @@ def _parse_ownership_pct(data: object) -> float | None | Unset: ownership_pct = _parse_ownership_pct(d.pop("ownership_pct", UNSET)) + def _parse_consolidation_method( + data: object, + ) -> None | Unset | UpdateEntityRequestConsolidationMethodType0: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + consolidation_method_type_0 = UpdateEntityRequestConsolidationMethodType0(data) + + return consolidation_method_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(None | Unset | UpdateEntityRequestConsolidationMethodType0, data) + + consolidation_method = _parse_consolidation_method( + d.pop("consolidation_method", UNSET) + ) + + def _parse_entity_role( + data: object, + ) -> None | Unset | UpdateEntityRequestEntityRoleType0: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, str): + raise TypeError() + entity_role_type_0 = UpdateEntityRequestEntityRoleType0(data) + + return entity_role_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(None | Unset | UpdateEntityRequestEntityRoleType0, data) + + entity_role = _parse_entity_role(d.pop("entity_role", UNSET)) + + def _parse_joined_on(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() + joined_on_type_0 = datetime.date.fromisoformat(data) + + return joined_on_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.date | None | Unset, data) + + joined_on = _parse_joined_on(d.pop("joined_on", UNSET)) + + def _parse_left_on(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() + left_on_type_0 = datetime.date.fromisoformat(data) + + return left_on_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(datetime.date | None | Unset, data) + + left_on = _parse_left_on(d.pop("left_on", UNSET)) + update_entity_request = cls( entity_id=entity_id, name=name, @@ -523,6 +674,10 @@ def _parse_ownership_pct(data: object) -> float | None | Unset: address_postal_code=address_postal_code, address_country=address_country, ownership_pct=ownership_pct, + consolidation_method=consolidation_method, + entity_role=entity_role, + joined_on=joined_on, + left_on=left_on, ) update_entity_request.additional_properties = d diff --git a/robosystems_client/models/update_entity_request_consolidation_method_type_0.py b/robosystems_client/models/update_entity_request_consolidation_method_type_0.py new file mode 100644 index 00000000..22eab1e4 --- /dev/null +++ b/robosystems_client/models/update_entity_request_consolidation_method_type_0.py @@ -0,0 +1,11 @@ +from enum import Enum + + +class UpdateEntityRequestConsolidationMethodType0(str, Enum): + COST = "cost" + EQUITY = "equity" + FULL = "full" + NONE = "none" + + def __str__(self) -> str: + return str(self.value) diff --git a/robosystems_client/models/update_entity_request_entity_role_type_0.py b/robosystems_client/models/update_entity_request_entity_role_type_0.py new file mode 100644 index 00000000..3b4e5f19 --- /dev/null +++ b/robosystems_client/models/update_entity_request_entity_role_type_0.py @@ -0,0 +1,9 @@ +from enum import Enum + + +class UpdateEntityRequestEntityRoleType0(str, Enum): + CONSOLIDATION = "consolidation" + OPERATING = "operating" + + def __str__(self) -> str: + return str(self.value) diff --git a/tests/test_ledger_client.py b/tests/test_ledger_client.py index f20f0381..5becea96 100644 --- a/tests/test_ledger_client.py +++ b/tests/test_ledger_client.py @@ -107,6 +107,10 @@ def test_get_entity_returns_typed_model(self, mock_execute, mock_config, graph_i "isParent": False, "parentEntityId": None, "ownershipPct": None, + "consolidationMethod": "none", + "entityRole": "operating", + "joinedOn": None, + "leftOn": None, "source": "qb", "sourceId": None, "sourceGraphId": None, @@ -153,6 +157,10 @@ def test_list_entities(self, mock_execute, mock_config, graph_id): "isParent": True, "parentEntityId": None, "ownershipPct": None, + "consolidationMethod": "full", + "entityRole": "operating", + "joinedOn": None, + "leftOn": None, "source": "qb", "sourceGraphId": None, "connectionId": None,