Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions robosystems_client/clients/ledger_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,10 @@
from ..graphql.generated.get_ledger_trial_balance import (
GetLedgerTrialBalanceTrialBalance as TrialBalance,
)
from ..graphql.generated.list_information_block_summaries import (
ListInformationBlockSummaries,
ListInformationBlockSummariesInformationBlockSummaries,
)
from ..graphql.generated.list_information_blocks import (
ListInformationBlocks,
ListInformationBlocksInformationBlocks,
Expand Down Expand Up @@ -475,6 +479,7 @@
GET_LEDGER_SUMMARY_GQL,
GET_LEDGER_TRANSACTION_GQL,
GET_LEDGER_TRIAL_BALANCE_GQL,
LIST_INFORMATION_BLOCK_SUMMARIES_GQL,
LIST_INFORMATION_BLOCKS_GQL,
LIST_LEDGER_ACCOUNTS_GQL,
LIST_LEDGER_BLOCKED_SOURCE_GRAPHS_GQL,
Expand Down Expand Up @@ -1587,6 +1592,41 @@ def list_information_blocks(
)
return ListInformationBlocks.model_validate(data).information_blocks

def list_information_block_summaries(
self,
graph_id: str,
*,
block_type: str | None = None,
category: str | None = None,
limit: int | None = None,
offset: int | None = None,
scenario_id: str | None = None,
entity_id: str | None = None,
) -> list[ListInformationBlockSummariesInformationBlockSummaries]:
"""List Information Blocks as identities and counts, one row per block.

The rows, filters, order and page of ``list_information_blocks``, read
in one query instead of an envelope build per block — the call that
fills a picker. ``fact_count > 0`` marks a block whose envelope carries
facts (a library-seeded structure variant carries none); a block's
atoms come from ``get_information_block``.
"""
data = self._query(
graph_id,
LIST_INFORMATION_BLOCK_SUMMARIES_GQL,
{
"blockType": block_type,
"category": category,
"limit": limit,
"offset": offset,
"scenarioId": scenario_id,
"entityId": entity_id,
},
)
return ListInformationBlockSummaries.model_validate(
data
).information_block_summaries

def create_information_block(
self,
graph_id: str,
Expand Down
8 changes: 8 additions & 0 deletions robosystems_client/graphql/generated/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@
)
from .get_library_taxonomy import GetLibraryTaxonomy, GetLibraryTaxonomyLibraryTaxonomy
from .list_chart_templates import ListChartTemplates, ListChartTemplatesChartTemplates
from .list_information_block_summaries import (
ListInformationBlockSummaries,
ListInformationBlockSummariesInformationBlockSummaries,
)
from .list_information_blocks import (
ListInformationBlocks,
ListInformationBlocksInformationBlocks,
Expand Down Expand Up @@ -380,6 +384,7 @@
GET_LIBRARY_ELEMENT_GQL,
GET_LIBRARY_TAXONOMY_GQL,
LIST_CHART_TEMPLATES_GQL,
LIST_INFORMATION_BLOCK_SUMMARIES_GQL,
LIST_INFORMATION_BLOCKS_GQL,
LIST_INVESTOR_PORTFOLIOS_GQL,
LIST_INVESTOR_POSITIONS_GQL,
Expand Down Expand Up @@ -601,6 +606,7 @@
"GraphQLClientInvalidResponseError",
"LIST_CHART_TEMPLATES_GQL",
"LIST_INFORMATION_BLOCKS_GQL",
"LIST_INFORMATION_BLOCK_SUMMARIES_GQL",
"LIST_INVESTOR_PORTFOLIOS_GQL",
"LIST_INVESTOR_POSITIONS_GQL",
"LIST_INVESTOR_SECURITIES_GQL",
Expand All @@ -626,6 +632,8 @@
"LIST_LIBRARY_TAXONOMY_ARCS_GQL",
"ListChartTemplates",
"ListChartTemplatesChartTemplates",
"ListInformationBlockSummaries",
"ListInformationBlockSummariesInformationBlockSummaries",
"ListInformationBlocks",
"ListInformationBlocksInformationBlocks",
"ListInformationBlocksInformationBlocksArtifact",
Expand Down
29 changes: 29 additions & 0 deletions robosystems_client/graphql/generated/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
from .get_library_element_equivalents import GetLibraryElementEquivalents
from .get_library_taxonomy import GetLibraryTaxonomy
from .list_chart_templates import ListChartTemplates
from .list_information_block_summaries import ListInformationBlockSummaries
from .list_information_blocks import ListInformationBlocks
from .list_investor_portfolios import ListInvestorPortfolios
from .list_investor_positions import ListInvestorPositions
Expand Down Expand Up @@ -97,6 +98,7 @@
GET_LIBRARY_ELEMENT_GQL,
GET_LIBRARY_TAXONOMY_GQL,
LIST_CHART_TEMPLATES_GQL,
LIST_INFORMATION_BLOCK_SUMMARIES_GQL,
LIST_INFORMATION_BLOCKS_GQL,
LIST_INVESTOR_PORTFOLIOS_GQL,
LIST_INVESTOR_POSITIONS_GQL,
Expand Down Expand Up @@ -616,6 +618,33 @@ def list_chart_templates(self, **kwargs: Any) -> ListChartTemplates:
data = self.get_data(response)
return ListChartTemplates.model_validate(data)

def list_information_block_summaries(
self,
block_type: Union[Optional[str], UnsetType] = UNSET,
category: Union[Optional[str], UnsetType] = UNSET,
limit: Union[Optional[int], UnsetType] = UNSET,
offset: Union[Optional[int], UnsetType] = UNSET,
scenario_id: Union[Optional[str], UnsetType] = UNSET,
entity_id: Union[Optional[str], UnsetType] = UNSET,
**kwargs: Any,
) -> ListInformationBlockSummaries:
variables: dict[str, object] = {
"blockType": block_type,
"category": category,
"limit": limit,
"offset": offset,
"scenarioId": scenario_id,
"entityId": entity_id,
}
response = self.execute(
query=LIST_INFORMATION_BLOCK_SUMMARIES_GQL,
operation_name="ListInformationBlockSummaries",
variables=variables,
**kwargs,
)
data = self.get_data(response)
return ListInformationBlockSummaries.model_validate(data)

def list_information_blocks(
self,
block_type: Union[Optional[str], UnsetType] = UNSET,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from typing import Optional

from pydantic import Field

from .base_model import BaseModel


class ListInformationBlockSummaries(BaseModel):
information_block_summaries: list[
"ListInformationBlockSummariesInformationBlockSummaries"
] = Field(alias="informationBlockSummaries")


class ListInformationBlockSummariesInformationBlockSummaries(BaseModel):
id: str
block_type: str = Field(alias="blockType")
name: str
display_name: str = Field(alias="displayName")
category: str
taxonomy_id: Optional[str] = Field(alias="taxonomyId")
taxonomy_name: Optional[str] = Field(alias="taxonomyName")
entity_id: Optional[str] = Field(alias="entityId")
fact_count: int = Field(alias="factCount")
connection_count: int = Field(alias="connectionCount")


ListInformationBlockSummaries.model_rebuild()
25 changes: 25 additions & 0 deletions robosystems_client/graphql/generated/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"GET_LIBRARY_TAXONOMY_GQL",
"LIST_CHART_TEMPLATES_GQL",
"LIST_INFORMATION_BLOCKS_GQL",
"LIST_INFORMATION_BLOCK_SUMMARIES_GQL",
"LIST_INVESTOR_PORTFOLIOS_GQL",
"LIST_INVESTOR_POSITIONS_GQL",
"LIST_INVESTOR_SECURITIES_GQL",
Expand Down Expand Up @@ -1242,6 +1243,30 @@
}
"""

LIST_INFORMATION_BLOCK_SUMMARIES_GQL = """
query ListInformationBlockSummaries($blockType: String, $category: String, $limit: Int, $offset: Int, $scenarioId: String, $entityId: String) {
informationBlockSummaries(
blockType: $blockType
category: $category
limit: $limit
offset: $offset
scenarioId: $scenarioId
entityId: $entityId
) {
id
blockType
name
displayName
category
taxonomyId
taxonomyName
entityId
factCount
connectionCount
}
}
"""

LIST_INFORMATION_BLOCKS_GQL = """
query ListInformationBlocks($blockType: String, $category: String, $limit: Int, $offset: Int, $scenarioId: String, $entityId: String) {
informationBlocks(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
query ListInformationBlockSummaries(
$blockType: String
$category: String
$limit: Int
$offset: Int
$scenarioId: String
$entityId: String
) {
informationBlockSummaries(
blockType: $blockType
category: $category
limit: $limit
offset: $offset
scenarioId: $scenarioId
entityId: $entityId
) {
id blockType name displayName category
taxonomyId taxonomyName entityId
factCount connectionCount
}
}
80 changes: 80 additions & 0 deletions robosystems_client/graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,43 @@ type Query {
entityId: String = null
): [InformationBlock!]!

"""
List Information Blocks as identities and counts, one row per block.

The rows, filters, order and page of `informationBlocks`, read in one
query instead of an envelope build per block — the call that fills a
picker or a rail. `factCount` says whether a block carries facts for
the entity read (a library-seeded structure variant carries none);
a block's atoms come from `informationBlock(id)`.
"""
informationBlockSummaries(
"""Filter to one registered block type, e.g. `schedule`."""
blockType: String = null

"""
Filter on the registry entry's category label, e.g. `Close` or `Reporting`.
"""
category: String = null

"""
Maximum rows to return, 1-1000. Omit to use this field's own default; out of range raises `INVALID_PAGINATION`.
"""
limit: Int = null

"""
Rows to skip before returning, 0 or greater. Out of range raises `INVALID_PAGINATION`.
"""
offset: Int = null

"""
A forecast block's structure id; its entity scopes the list when `entityId` is omitted.
"""
scenarioId: String = null

"""The entity whose blocks and facts to list. Omit for the group parent."""
entityId: String = null
): [InformationBlockSummary!]!

"""Fetch a single Taxonomy Block envelope by id."""
taxonomyBlock(
"""The taxonomy block's structure id."""
Expand Down Expand Up @@ -3809,6 +3846,11 @@ type FactRow {

"""Indentation depth in the structure hierarchy (0 = root)."""
depth: Int!

"""
On a roll-forward, `start` for the beginning-balance row and `end` for the ending-balance row — one concept, two rows. Null elsewhere.
"""
periodRole: String
}

"""
Expand Down Expand Up @@ -3948,6 +3990,44 @@ type BlockedSourceGraph {
reason: String
}

"""
One row of a block list: the envelope's identity with counts in place
of its atoms. Read in one query, so a graph's whole catalogue lists in the
time one envelope builds.
"""
type InformationBlockSummary {
id: String!

"""Discriminator — 'schedule', …"""
blockType: String!
name: String!

"""Registry-sourced display label (e.g., 'Schedule')."""
displayName: String!

"""Registry-sourced sidebar grouping ('Close', 'Reporting', …)."""
category: String!

"""Source taxonomy the Structure was seeded from."""
taxonomyId: String

"""Display name of the source taxonomy."""
taxonomyName: String

"""
The entity whose books the block reads: its owner for a schedule, reconciliation or forecast; the entity asked for, else the group parent, on a block shared by the group. Null on the library.
"""
entityId: String

"""
Facts in the block's scope for that entity, every set — what its envelope carries. Zero on a library-seeded structure variant and on a schedule that has run off into history, which a picker leaves out.
"""
factCount: Int!

"""Arcs the block's structure carries."""
connectionCount: Int!
}

type TaxonomyBlock {
id: ID!
name: String!
Expand Down
16 changes: 16 additions & 0 deletions tests/test_facade_wire_shapes.py
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,22 @@ def test_create_report_sends_the_entity(self, httpx_mock):
body = json.loads(httpx_mock.get_requests()[0].content)
assert body["entity_id"] == "ent_sub"

def test_list_information_block_summaries_sends_filters(self, httpx_mock):
httpx_mock.add_response(
method="POST",
url=f"{BASE}/extensions/{GRAPH}/graphql",
json={"data": {"informationBlockSummaries": []}},
)

blocks = LedgerClient(CONFIG).list_information_block_summaries(
GRAPH, block_type="forecast", entity_id="ent_sub"
)

assert blocks == []
payload = json.loads(httpx_mock.get_requests()[0].content)
assert payload["variables"] == {"blockType": "forecast", "entityId": "ent_sub"}
assert "informationBlockSummaries" in payload["query"]

def test_list_information_blocks_sends_scenario_id(self, httpx_mock):
httpx_mock.add_response(
method="POST",
Expand Down
28 changes: 28 additions & 0 deletions tests/test_ledger_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1674,6 +1674,34 @@ def test_list_information_blocks(self, mock_execute, mock_config, graph_id):
variables = mock_execute.call_args[0][2]
assert variables["blockType"] == "schedule"

@patch("robosystems_client.graphql.client.GraphQLClient.execute")
def test_list_information_block_summaries(self, mock_execute, mock_config, graph_id):
mock_execute.return_value = {
"informationBlockSummaries": [
{
"id": "str_sched_1",
"blockType": "schedule",
"name": "Depreciation",
"displayName": "Schedule",
"category": "Close",
"taxonomyId": "tax_01",
"taxonomyName": "My CoA",
"entityId": "ent_parent",
"factCount": 12,
"connectionCount": 3,
}
]
}
client = LedgerClient(mock_config)
result = client.list_information_block_summaries(graph_id, limit=200)
assert len(result) == 1
assert result[0].id == "str_sched_1"
assert result[0].block_type == "schedule"
assert (result[0].fact_count, result[0].connection_count) == (12, 3)
assert not hasattr(result[0], "facts")
variables = mock_execute.call_args[0][2]
assert variables["limit"] == 200

@patch("robosystems_client.graphql.client.GraphQLClient.execute")
def test_get_information_block(self, mock_execute, mock_config, graph_id):
mock_execute.return_value = {
Expand Down
Loading