From 24c4c492e3ec1e1da7fab0dcd45615fb024c0e50 Mon Sep 17 00:00:00 2001 From: "Joseph T. French" Date: Thu, 26 Feb 2026 13:00:54 -0600 Subject: [PATCH 1/4] Refactor SDK aliases in `__init__.py` - Updated the SDK aliases to improve clarity by renaming `RoboSystemsClient` for better understanding. - Added `RoboSystemsClient` to the `__all__` export list to ensure it is accessible for users of the SDK. These changes enhance the usability and readability of the SDK's interface. --- robosystems_client/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/robosystems_client/__init__.py b/robosystems_client/__init__.py index d643eaf..ef70525 100644 --- a/robosystems_client/__init__.py +++ b/robosystems_client/__init__.py @@ -2,12 +2,14 @@ from .client import AuthenticatedClient, Client -# Convenience alias for the main SDK +# Convenience aliases for the main SDK +RoboSystemsClient = AuthenticatedClient RoboSystemsSDK = AuthenticatedClient __all__ = ( "AuthenticatedClient", "Client", + "RoboSystemsClient", "RoboSystemsSDK", ) From 1b9a01c66beb626ea00bebfdd085e5fd159468b1 Mon Sep 17 00:00:00 2001 From: "Joseph T. French" Date: Fri, 27 Feb 2026 12:30:05 -0600 Subject: [PATCH 2/4] Refactor element mapping client and update view builder client - Removed the `ElementMappingClient` and associated classes from the codebase to streamline the SDK and eliminate unused functionality. - Updated the `ViewBuilderClient` to remove references to the `ElementMappingClient`, simplifying its initialization and method signatures. These changes enhance the clarity and maintainability of the SDK by focusing on essential components. --- robosystems_client/extensions/__init__.py | 11 - .../extensions/element_mapping_client.py | 585 ------------------ .../extensions/view_builder_client.py | 27 +- 3 files changed, 6 insertions(+), 617 deletions(-) delete mode 100644 robosystems_client/extensions/element_mapping_client.py diff --git a/robosystems_client/extensions/__init__.py b/robosystems_client/extensions/__init__.py index c5ff74d..6962fac 100644 --- a/robosystems_client/extensions/__init__.py +++ b/robosystems_client/extensions/__init__.py @@ -56,12 +56,6 @@ RoboSystemsExtensionConfig, AsyncRoboSystemsExtensions, ) -from .element_mapping_client import ( - ElementMappingClient, - MappingStructure, - ElementAssociation, - AggregationMethod, -) from .subgraph_workspace_client import ( SubgraphWorkspaceClient, SubgraphWorkspace, @@ -145,11 +139,6 @@ "RoboSystemsExtensions", "RoboSystemsExtensionConfig", "AsyncRoboSystemsExtensions", - # Element Mapping Client - "ElementMappingClient", - "MappingStructure", - "ElementAssociation", - "AggregationMethod", # Subgraph Workspace Client "SubgraphWorkspaceClient", "SubgraphWorkspace", diff --git a/robosystems_client/extensions/element_mapping_client.py b/robosystems_client/extensions/element_mapping_client.py deleted file mode 100644 index 86f6d23..0000000 --- a/robosystems_client/extensions/element_mapping_client.py +++ /dev/null @@ -1,585 +0,0 @@ -"""Element Mapping Client Extension - -Client-side extension for managing element mappings in subgraph workspaces. -Constructs Cypher queries for execution via the public /query endpoint. - -This replaces server-side mapping endpoints with client-side logic, -following the architecture where mappings are written to subgraphs -and later published to the main graph via parquet export/ingest. -""" - -import uuid -from typing import List, Optional -from dataclasses import dataclass -from enum import Enum -import pandas as pd - - -class AggregationMethod(Enum): - """Aggregation methods for element mapping""" - - SUM = "sum" - AVERAGE = "average" - WEIGHTED_AVERAGE = "weighted_average" - FIRST = "first" - LAST = "last" - CALCULATED = "calculated" - - -@dataclass -class MappingStructure: - """Element mapping structure""" - - identifier: str - name: str - description: Optional[str] = None - taxonomy_uri: Optional[str] = None - target_taxonomy_uri: Optional[str] = None - associations: Optional[List["ElementAssociation"]] = None - - def __post_init__(self): - if self.associations is None: - self.associations = [] - - -@dataclass -class ElementAssociation: - """Association between source and target elements""" - - identifier: str - source_element: str - target_element: str - aggregation_method: AggregationMethod = AggregationMethod.SUM - weight: float = 1.0 - formula: Optional[str] = None - order_value: float = 1.0 - - -class ElementMappingClient: - """ - Client for managing element mappings in subgraph workspaces. - - All operations construct Cypher queries that are executed via the - public /query endpoint against a subgraph workspace. - """ - - def __init__(self, query_client): - """ - Initialize with a query client for executing Cypher. - - Args: - query_client: RoboSystemsExtensions query client - """ - self.query = query_client - - def _generate_uuid(self, seed: str = None) -> str: - """Generate a deterministic or random UUID""" - if seed: - # For deterministic UUID based on seed - import hashlib - - hash_obj = hashlib.sha256(seed.encode()) - hash_hex = hash_obj.hexdigest() - return f"{hash_hex[:8]}-{hash_hex[8:12]}-7{hash_hex[13:16]}-{hash_hex[16:20]}-{hash_hex[20:32]}" - else: - return str(uuid.uuid4()) - - async def create_mapping_structure( - self, - graph_id: str, - name: str, - description: str = None, - taxonomy_uri: str = None, - target_taxonomy_uri: str = None, - ) -> MappingStructure: - """ - Create a new element mapping structure in the subgraph. - - Args: - graph_id: Subgraph workspace ID (e.g., kg123_workspace) - name: Name of the mapping structure - description: Optional description - taxonomy_uri: Source taxonomy URI (e.g., "qb:chart-of-accounts") - target_taxonomy_uri: Target taxonomy URI (e.g., "us-gaap:2024") - - Returns: - Created MappingStructure - """ - structure_id = self._generate_uuid(f"mapping_structure_{name}_{graph_id}") - - cypher = """ - CREATE (s:Structure { - identifier: $identifier, - type: 'ElementMapping', - name: $name, - definition: $description, - uri: $uri, - network_uri: $network_uri - }) - RETURN s - """ - - params = { - "identifier": structure_id, - "name": name, - "description": description or "", - "uri": taxonomy_uri or "", - "network_uri": target_taxonomy_uri or "", - } - - self.query.query(graph_id, cypher, params) - - return MappingStructure( - identifier=structure_id, - name=name, - description=description, - taxonomy_uri=taxonomy_uri, - target_taxonomy_uri=target_taxonomy_uri, - associations=[], - ) - - async def get_mapping_structure( - self, graph_id: str, structure_id: str - ) -> Optional[MappingStructure]: - """ - Get a mapping structure with all its associations. - - Args: - graph_id: Subgraph workspace ID - structure_id: Structure identifier - - Returns: - MappingStructure with associations, or None if not found - """ - cypher = """ - MATCH (s:Structure) - WHERE s.identifier = $structure_id AND s.type = 'ElementMapping' - OPTIONAL MATCH (s)-[:STRUCTURE_HAS_ASSOCIATION]->(a:Association) - OPTIONAL MATCH (a)-[:ASSOCIATION_HAS_FROM_ELEMENT]->(from_el:Element) - OPTIONAL MATCH (a)-[:ASSOCIATION_HAS_TO_ELEMENT]->(to_el:Element) - RETURN s, - collect({ - identifier: a.identifier, - source_element: from_el.uri, - target_element: to_el.uri, - aggregation_method: a.preferred_label, - weight: a.weight, - order_value: a.order_value - }) as associations - """ - - result = self.query.query(graph_id, cypher, {"structure_id": structure_id}) - - if not result or not result.data: - return None - - row = result.data[0] - structure_data = row["s"] - - associations = [] - for assoc in row["associations"]: - if assoc["identifier"]: - associations.append( - ElementAssociation( - identifier=assoc["identifier"], - source_element=assoc["source_element"] or "", - target_element=assoc["target_element"] or "", - aggregation_method=AggregationMethod(assoc["aggregation_method"] or "sum"), - weight=assoc["weight"] or 1.0, - order_value=assoc["order_value"] or 1.0, - ) - ) - - return MappingStructure( - identifier=structure_data["identifier"], - name=structure_data["name"], - description=structure_data.get("definition"), - taxonomy_uri=structure_data.get("uri"), - target_taxonomy_uri=structure_data.get("network_uri"), - associations=associations, - ) - - async def list_mapping_structures(self, graph_id: str) -> List[MappingStructure]: - """ - List all mapping structures in the subgraph. - - Args: - graph_id: Subgraph workspace ID - - Returns: - List of MappingStructure objects - """ - cypher = """ - MATCH (s:Structure) - WHERE s.type = 'ElementMapping' - OPTIONAL MATCH (s)-[:STRUCTURE_HAS_ASSOCIATION]->(a:Association) - RETURN s, - count(a) as association_count - ORDER BY s.name - """ - - result = self.query.query(graph_id, cypher, {}) - - structures = [] - if result and result.data: - for row in result.data: - structure_data = row["s"] - structures.append( - MappingStructure( - identifier=structure_data["identifier"], - name=structure_data["name"], - description=structure_data.get("definition"), - taxonomy_uri=structure_data.get("uri"), - target_taxonomy_uri=structure_data.get("network_uri"), - associations=[], # Not loading associations in list view - ) - ) - - return structures - - async def create_association( - self, - graph_id: str, - structure_id: str, - source_element: str, - target_element: str, - aggregation_method: AggregationMethod = AggregationMethod.SUM, - weight: float = 1.0, - order_value: float = 1.0, - ) -> ElementAssociation: - """ - Add an association to a mapping structure. - - Creates an Association node linking source element to target element. - If the target element doesn't exist, it will be created. - - Args: - graph_id: Subgraph workspace ID - structure_id: Structure identifier - source_element: Source element URI (e.g., "qb:BankAccount1") - target_element: Target element URI (e.g., "us-gaap:Cash") - aggregation_method: How to aggregate values - weight: Weight for weighted aggregation - order_value: Display order - - Returns: - Created ElementAssociation - """ - association_id = self._generate_uuid( - f"association_{structure_id}_{source_element}_{target_element}" - ) - - # Generate identifier for target element - target_element_id = self._generate_uuid(f"element_{target_element}") - target_element_name = ( - target_element.split(":")[-1] if ":" in target_element else target_element - ) - - cypher = """ - MATCH (s:Structure) - WHERE s.identifier = $structure_id AND s.type = 'ElementMapping' - MATCH (from_el:Element {uri: $source_element}) - MERGE (to_el:Element {identifier: $target_element_identifier}) - ON CREATE SET to_el.uri = $target_element, to_el.name = $target_element_name - CREATE (a:Association { - identifier: $identifier, - association_type: 'ElementMapping', - arcrole: 'aggregation', - preferred_label: $preferred_label, - weight: $weight, - order_value: $order_value - }) - CREATE (s)-[:STRUCTURE_HAS_ASSOCIATION]->(a) - CREATE (a)-[:ASSOCIATION_HAS_FROM_ELEMENT]->(from_el) - CREATE (a)-[:ASSOCIATION_HAS_TO_ELEMENT]->(to_el) - RETURN a - """ - - params = { - "structure_id": structure_id, - "identifier": association_id, - "preferred_label": aggregation_method.value, - "weight": weight, - "order_value": order_value, - "source_element": source_element, - "target_element": target_element, - "target_element_identifier": target_element_id, - "target_element_name": target_element_name, - } - - self.query.query(graph_id, cypher, params) - - return ElementAssociation( - identifier=association_id, - source_element=source_element, - target_element=target_element, - aggregation_method=aggregation_method, - weight=weight, - order_value=order_value, - ) - - async def update_association( - self, - graph_id: str, - structure_id: str, - association_id: str, - aggregation_method: AggregationMethod = None, - weight: float = None, - order_value: float = None, - ) -> Optional[ElementAssociation]: - """ - Update an existing association. - - Args: - graph_id: Subgraph workspace ID - structure_id: Structure identifier - association_id: Association identifier - aggregation_method: New aggregation method - weight: New weight - order_value: New order value - - Returns: - Updated ElementAssociation, or None if not found - """ - set_clauses = [] - params = {"structure_id": structure_id, "association_id": association_id} - - if aggregation_method is not None: - set_clauses.append("a.preferred_label = $aggregation_method") - params["aggregation_method"] = aggregation_method.value - - if weight is not None: - set_clauses.append("a.weight = $weight") - params["weight"] = weight - - if order_value is not None: - set_clauses.append("a.order_value = $order_value") - params["order_value"] = order_value - - if not set_clauses: - return None - - update_cypher = f""" - MATCH (s:Structure)-[:STRUCTURE_HAS_ASSOCIATION]->(a:Association) - WHERE s.identifier = $structure_id AND a.identifier = $association_id - SET {", ".join(set_clauses)} - RETURN a - """ - - self.query.query(graph_id, update_cypher, params) - - # Get updated association - get_cypher = """ - MATCH (s:Structure)-[:STRUCTURE_HAS_ASSOCIATION]->(a:Association) - WHERE s.identifier = $structure_id AND a.identifier = $association_id - MATCH (a)-[:ASSOCIATION_HAS_FROM_ELEMENT]->(from_el:Element) - MATCH (a)-[:ASSOCIATION_HAS_TO_ELEMENT]->(to_el:Element) - RETURN a, from_el.uri as source_element, to_el.uri as target_element - """ - - result = self.query.query(graph_id, get_cypher, params) - - if not result or not result.data: - return None - - row = result.data[0] - assoc_data = row["a"] - - return ElementAssociation( - identifier=assoc_data["identifier"], - source_element=row["source_element"], - target_element=row["target_element"], - aggregation_method=AggregationMethod(assoc_data["preferred_label"]), - weight=assoc_data["weight"], - order_value=assoc_data["order_value"], - ) - - async def delete_association( - self, graph_id: str, structure_id: str, association_id: str - ) -> bool: - """ - Delete an association from a mapping structure. - - Args: - graph_id: Subgraph workspace ID - structure_id: Structure identifier - association_id: Association identifier - - Returns: - True if deleted - """ - cypher = """ - MATCH (s:Structure)-[:STRUCTURE_HAS_ASSOCIATION]->(a:Association) - WHERE s.identifier = $structure_id AND a.identifier = $association_id - DETACH DELETE a - """ - - self.query.query( - graph_id, cypher, {"structure_id": structure_id, "association_id": association_id} - ) - - return True - - async def delete_mapping_structure(self, graph_id: str, structure_id: str) -> bool: - """ - Delete a mapping structure and all its associations. - - Args: - graph_id: Subgraph workspace ID - structure_id: Structure identifier - - Returns: - True if deleted - """ - cypher = """ - MATCH (s:Structure) - WHERE s.identifier = $structure_id AND s.type = 'ElementMapping' - OPTIONAL MATCH (s)-[:STRUCTURE_HAS_ASSOCIATION]->(a:Association) - DETACH DELETE s, a - """ - - self.query.query(graph_id, cypher, {"structure_id": structure_id}) - - return True - - @staticmethod - def apply_element_mapping( - fact_data: pd.DataFrame, mapping_structure: MappingStructure - ) -> pd.DataFrame: - """ - Apply element mapping to aggregate source elements into target elements. - - This is a client-side pandas operation that doesn't require graph access. - - Args: - fact_data: DataFrame with columns including element_id, numeric_value, etc. - mapping_structure: MappingStructure with associations defining aggregation - - Returns: - DataFrame with aggregated facts mapped to target elements - """ - if fact_data.empty or not mapping_structure.associations: - return fact_data - - df = fact_data.copy() - aggregated_rows = [] - - # Handle both numeric_value (from facts) and net_balance (from trial balance) - value_col = "numeric_value" if "numeric_value" in df.columns else "net_balance" - - # Group associations by target element - target_groups = {} - for assoc in mapping_structure.associations: - if assoc.target_element not in target_groups: - target_groups[assoc.target_element] = [] - target_groups[assoc.target_element].append(assoc) - - # Build URI to ID mapping if both columns exist - uri_to_id_map = {} - if "element_uri" in df.columns and "element_id" in df.columns: - for _, row in df[["element_uri", "element_id"]].drop_duplicates().iterrows(): - uri_to_id_map[row["element_uri"]] = row["element_id"] - - # Determine groupby columns - groupby_columns = [] - if "period_end" in df.columns: - groupby_columns.append("period_end") - if "period_start" in df.columns: - groupby_columns.append("period_start") - if "entity_id" in df.columns: - groupby_columns.append("entity_id") - if "dimension_axis" in df.columns: - groupby_columns.append("dimension_axis") - if "dimension_member" in df.columns: - groupby_columns.append("dimension_member") - - # Aggregate for each target element - for target_element, associations in target_groups.items(): - # Map source URIs to IDs - source_element_uris = [assoc.source_element for assoc in associations] - source_element_ids = [uri_to_id_map.get(uri, uri) for uri in source_element_uris] - - # Filter source facts - source_facts = df[df["element_id"].isin(source_element_ids)].copy() - - if source_facts.empty: - continue - - aggregation_method = associations[0].aggregation_method - - if groupby_columns: - # Group and aggregate - for group_keys, group_df in source_facts.groupby(groupby_columns): - aggregated_value = ElementMappingClient._aggregate_values( - group_df, associations, aggregation_method, value_col - ) - - # Create aggregated row - aggregated_row = group_df.iloc[0].copy() - aggregated_row["element_id"] = target_element - aggregated_row["element_name"] = target_element.split(":")[-1] - aggregated_row[value_col] = aggregated_value - - if "element_label" in aggregated_row: - aggregated_row["element_label"] = target_element.split(":")[-1] - - aggregated_rows.append(aggregated_row) - else: - # No grouping, aggregate all - aggregated_value = ElementMappingClient._aggregate_values( - source_facts, associations, aggregation_method, value_col - ) - - aggregated_row = source_facts.iloc[0].copy() - aggregated_row["element_id"] = target_element - aggregated_row["element_name"] = target_element.split(":")[-1] - aggregated_row[value_col] = aggregated_value - - if "element_label" in aggregated_row: - aggregated_row["element_label"] = target_element.split(":")[-1] - - aggregated_rows.append(aggregated_row) - - if not aggregated_rows: - return df - - return pd.DataFrame(aggregated_rows) - - @staticmethod - def _aggregate_values( - facts: pd.DataFrame, - associations: List[ElementAssociation], - method: AggregationMethod, - value_col: str, - ) -> float: - """Helper function to aggregate values based on method.""" - if method == AggregationMethod.SUM: - return facts[value_col].sum() - - elif method == AggregationMethod.AVERAGE: - return facts[value_col].mean() - - elif method == AggregationMethod.WEIGHTED_AVERAGE: - weights_map = {assoc.source_element: assoc.weight for assoc in associations} - facts_with_weights = facts.copy() - facts_with_weights["weight"] = facts_with_weights["element_id"].map(weights_map) - facts_with_weights["weighted_value"] = ( - facts_with_weights[value_col] * facts_with_weights["weight"] - ) - total_weight = facts_with_weights["weight"].sum() - if total_weight == 0: - return 0.0 - return facts_with_weights["weighted_value"].sum() / total_weight - - elif method == AggregationMethod.FIRST: - return facts[value_col].iloc[0] - - elif method == AggregationMethod.LAST: - return facts[value_col].iloc[-1] - - elif method == AggregationMethod.CALCULATED: - # For calculated, use sum as default (could be customized) - return facts[value_col].sum() - - # Default to sum - return facts[value_col].sum() diff --git a/robosystems_client/extensions/view_builder_client.py b/robosystems_client/extensions/view_builder_client.py index ed5bdf6..6cbaa33 100644 --- a/robosystems_client/extensions/view_builder_client.py +++ b/robosystems_client/extensions/view_builder_client.py @@ -69,16 +69,14 @@ class ViewBuilderClient: - Write views to subgraph workspaces """ - def __init__(self, query_client, element_mapping_client=None): + def __init__(self, query_client): """ - Initialize with query client and optional element mapping client. + Initialize with query client. Args: query_client: RoboSystems query client - element_mapping_client: Optional ElementMappingClient for applying mappings """ self.query = query_client - self.element_mapping = element_mapping_client async def aggregate_trial_balance( self, @@ -253,7 +251,6 @@ async def create_view( graph_id: str, source: ViewSource, view_config: Optional[ViewConfig] = None, - mapping_structure_id: Optional[str] = None, workspace_id: Optional[str] = None, ) -> ViewResponse: """ @@ -261,15 +258,13 @@ async def create_view( This is the main entry point for view generation. It: 1. Queries source data (transactions or facts) - 2. Applies element mappings if specified - 3. Generates pivot table presentation if configured - 4. Optionally writes to subgraph workspace + 2. Generates pivot table presentation if configured + 3. Optionally writes to subgraph workspace Args: graph_id: Main graph ID to query data from source: Source configuration (transactions or fact set) view_config: Optional pivot table configuration - mapping_structure_id: Optional mapping to apply for aggregation workspace_id: Optional subgraph to write results to Returns: @@ -300,20 +295,11 @@ async def create_view( else: raise ValueError(f"Unsupported source type: {source.type}") - # Step 2: Apply element mapping if specified - if mapping_structure_id and self.element_mapping: - # Get mapping structure from subgraph - mapping = await self.element_mapping.get_mapping_structure( - workspace_id or graph_id, mapping_structure_id - ) - if mapping: - fact_data = self.element_mapping.apply_element_mapping(fact_data, mapping) - - # Step 3: Generate pivot table if configured + # Step 2: Generate pivot table if configured if view_config: fact_data = self._generate_pivot_table(fact_data, view_config) - # Step 4: Write to workspace if specified + # Step 3: Write to workspace if specified if workspace_id: await self._write_to_workspace(workspace_id, fact_data, source_type) @@ -326,7 +312,6 @@ async def create_view( "fact_count": len(fact_data), "period_start": source.period_start, "period_end": source.period_end, - "has_mapping": mapping_structure_id is not None, "has_pivot": view_config is not None, }, execution_time_ms=execution_time, From 98743ab23659cb33c2f8a82dfd25516f197c4db9 Mon Sep 17 00:00:00 2001 From: "Joseph T. French" Date: Fri, 27 Feb 2026 12:43:01 -0600 Subject: [PATCH 3/4] Remove element mapping references from ViewBuilderClient to streamline functionality and enhance clarity. --- robosystems_client/extensions/view_builder_client.py | 1 - 1 file changed, 1 deletion(-) diff --git a/robosystems_client/extensions/view_builder_client.py b/robosystems_client/extensions/view_builder_client.py index 6cbaa33..711e513 100644 --- a/robosystems_client/extensions/view_builder_client.py +++ b/robosystems_client/extensions/view_builder_client.py @@ -64,7 +64,6 @@ class ViewBuilderClient: Provides functionality to: - Query trial balance from transactions - Query existing facts with aspects - - Apply element mappings for aggregation - Generate pivot table presentations - Write views to subgraph workspaces """ From 840e5b63e580f7e6f3250382fb1acffeff50a050 Mon Sep 17 00:00:00 2001 From: "Joseph T. French" Date: Fri, 27 Feb 2026 22:19:44 -0600 Subject: [PATCH 4/4] Remove Plaid references from connection-related files and update connection models - Eliminated all Plaid-related documentation and references from the connection API files, including `create_connection.py`, `get_connection_options.py`, `sync_connection.py`, and `list_connections.py`. - Updated the `ConnectionResponse` and `CreateConnectionRequest` models to remove Plaid-specific attributes and adjust entity_id handling. - Deleted unused Plaid connection configuration models to streamline the codebase. These changes enhance clarity and focus on the remaining connection providers, improving maintainability of the SDK. --- .../api/connections/create_connection.py | 20 -- .../api/connections/get_connection_options.py | 20 -- .../api/connections/list_connections.py | 8 +- .../api/connections/sync_connection.py | 20 -- .../api/graphs/get_available_extensions.py | 12 +- robosystems_client/api/views/__init__.py | 1 + robosystems_client/api/views/create_view.py | 204 +++++++++++++ robosystems_client/models/__init__.py | 20 +- .../connection_provider_info_provider.py | 1 - .../models/connection_response.py | 28 +- .../models/create_connection_request.py | 56 ++-- .../create_connection_request_provider.py | 1 - .../models/create_view_request.py | 228 +++++++++++++++ .../list_connections_provider_type_0.py | 1 - .../models/plaid_connection_config.py | 209 ------------- .../models/sec_connection_config.py | 26 +- robosystems_client/models/view_axis_config.py | 276 ++++++++++++++++++ ...view_axis_config_element_labels_type_0.py} | 16 +- ... view_axis_config_member_labels_type_0.py} | 16 +- robosystems_client/models/view_config.py | 127 ++++++++ 20 files changed, 914 insertions(+), 376 deletions(-) create mode 100644 robosystems_client/api/views/__init__.py create mode 100644 robosystems_client/api/views/create_view.py create mode 100644 robosystems_client/models/create_view_request.py delete mode 100644 robosystems_client/models/plaid_connection_config.py create mode 100644 robosystems_client/models/view_axis_config.py rename robosystems_client/models/{plaid_connection_config_institution_type_0.py => view_axis_config_element_labels_type_0.py} (65%) rename robosystems_client/models/{plaid_connection_config_accounts_type_0_item.py => view_axis_config_member_labels_type_0.py} (65%) create mode 100644 robosystems_client/models/view_config.py diff --git a/robosystems_client/api/connections/create_connection.py b/robosystems_client/api/connections/create_connection.py index ba6094d..f46e6b4 100644 --- a/robosystems_client/api/connections/create_connection.py +++ b/robosystems_client/api/connections/create_connection.py @@ -107,11 +107,6 @@ def sync_detailed( - Requires admin permissions in QuickBooks - Complete with OAuth callback - **Plaid Connections**: - - Returns Plaid Link token - - User completes bank authentication - - Exchange public token for access - Note: This operation is included - no credit consumption required. @@ -161,11 +156,6 @@ def sync( - Requires admin permissions in QuickBooks - Complete with OAuth callback - **Plaid Connections**: - - Returns Plaid Link token - - User completes bank authentication - - Exchange public token for access - Note: This operation is included - no credit consumption required. @@ -210,11 +200,6 @@ async def asyncio_detailed( - Requires admin permissions in QuickBooks - Complete with OAuth callback - **Plaid Connections**: - - Returns Plaid Link token - - User completes bank authentication - - Exchange public token for access - Note: This operation is included - no credit consumption required. @@ -262,11 +247,6 @@ async def asyncio( - Requires admin permissions in QuickBooks - Complete with OAuth callback - **Plaid Connections**: - - Returns Plaid Link token - - User completes bank authentication - - Exchange public token for access - Note: This operation is included - no credit consumption required. diff --git a/robosystems_client/api/connections/get_connection_options.py b/robosystems_client/api/connections/get_connection_options.py index 718225b..2688e9f 100644 --- a/robosystems_client/api/connections/get_connection_options.py +++ b/robosystems_client/api/connections/get_connection_options.py @@ -86,11 +86,6 @@ def sync_detailed( - Chart of accounts, transactions, trial balance - Real-time sync capabilities - **Plaid**: Bank account connections - - Secure bank authentication via Plaid Link - - Transaction history and balances - - Multi-account support - No credits are consumed for viewing connection options. Args: @@ -136,11 +131,6 @@ def sync( - Chart of accounts, transactions, trial balance - Real-time sync capabilities - **Plaid**: Bank account connections - - Secure bank authentication via Plaid Link - - Transaction history and balances - - Multi-account support - No credits are consumed for viewing connection options. Args: @@ -181,11 +171,6 @@ async def asyncio_detailed( - Chart of accounts, transactions, trial balance - Real-time sync capabilities - **Plaid**: Bank account connections - - Secure bank authentication via Plaid Link - - Transaction history and balances - - Multi-account support - No credits are consumed for viewing connection options. Args: @@ -229,11 +214,6 @@ async def asyncio( - Chart of accounts, transactions, trial balance - Real-time sync capabilities - **Plaid**: Bank account connections - - Secure bank authentication via Plaid Link - - Transaction history and balances - - Multi-account support - No credits are consumed for viewing connection options. Args: diff --git a/robosystems_client/api/connections/list_connections.py b/robosystems_client/api/connections/list_connections.py index 8f2e8ae..e120d91 100644 --- a/robosystems_client/api/connections/list_connections.py +++ b/robosystems_client/api/connections/list_connections.py @@ -109,7 +109,7 @@ def sync_detailed( Returns active and inactive connections with their current status. Connections can be filtered by: - **Entity**: Show connections for a specific entity - - **Provider**: Filter by connection type (sec, quickbooks, plaid) + - **Provider**: Filter by connection type (sec, quickbooks) Each connection shows: - Current sync status and health @@ -159,7 +159,7 @@ def sync( Returns active and inactive connections with their current status. Connections can be filtered by: - **Entity**: Show connections for a specific entity - - **Provider**: Filter by connection type (sec, quickbooks, plaid) + - **Provider**: Filter by connection type (sec, quickbooks) Each connection shows: - Current sync status and health @@ -204,7 +204,7 @@ async def asyncio_detailed( Returns active and inactive connections with their current status. Connections can be filtered by: - **Entity**: Show connections for a specific entity - - **Provider**: Filter by connection type (sec, quickbooks, plaid) + - **Provider**: Filter by connection type (sec, quickbooks) Each connection shows: - Current sync status and health @@ -252,7 +252,7 @@ async def asyncio( Returns active and inactive connections with their current status. Connections can be filtered by: - **Entity**: Show connections for a specific entity - - **Provider**: Filter by connection type (sec, quickbooks, plaid) + - **Provider**: Filter by connection type (sec, quickbooks) Each connection shows: - Current sync status and health diff --git a/robosystems_client/api/connections/sync_connection.py b/robosystems_client/api/connections/sync_connection.py index cb73e07..5be23fe 100644 --- a/robosystems_client/api/connections/sync_connection.py +++ b/robosystems_client/api/connections/sync_connection.py @@ -112,11 +112,6 @@ def sync_detailed( - Generates fresh trial balance - Duration depends on data volume - **Plaid Sync**: - - Retrieves recent bank transactions - - Updates account balances - - Categorizes new transactions - Note: This operation is included - no credit consumption required. @@ -172,11 +167,6 @@ def sync( - Generates fresh trial balance - Duration depends on data volume - **Plaid Sync**: - - Retrieves recent bank transactions - - Updates account balances - - Categorizes new transactions - Note: This operation is included - no credit consumption required. @@ -229,11 +219,6 @@ async def asyncio_detailed( - Generates fresh trial balance - Duration depends on data volume - **Plaid Sync**: - - Retrieves recent bank transactions - - Updates account balances - - Categorizes new transactions - Note: This operation is included - no credit consumption required. @@ -287,11 +272,6 @@ async def asyncio( - Generates fresh trial balance - Duration depends on data volume - **Plaid Sync**: - - Retrieves recent bank transactions - - Updates account balances - - Categorizes new transactions - Note: This operation is included - no credit consumption required. diff --git a/robosystems_client/api/graphs/get_available_extensions.py b/robosystems_client/api/graphs/get_available_extensions.py index d5e65aa..c2eec98 100644 --- a/robosystems_client/api/graphs/get_available_extensions.py +++ b/robosystems_client/api/graphs/get_available_extensions.py @@ -61,7 +61,8 @@ def sync_detailed( **Available Extensions:** - **RoboLedger**: Complete accounting system with XBRL reporting, general ledger, and financial statements - - **RoboInvestor**: Investment portfolio management and tracking + - **RoboInvestor**: Investment portfolio management with securities tracking, trade execution, and + risk analysis - **RoboSCM**: Supply chain management and logistics - **RoboFO**: Front office operations and CRM - **RoboHRM**: Human resources management @@ -114,7 +115,8 @@ def sync( **Available Extensions:** - **RoboLedger**: Complete accounting system with XBRL reporting, general ledger, and financial statements - - **RoboInvestor**: Investment portfolio management and tracking + - **RoboInvestor**: Investment portfolio management with securities tracking, trade execution, and + risk analysis - **RoboSCM**: Supply chain management and logistics - **RoboFO**: Front office operations and CRM - **RoboHRM**: Human resources management @@ -163,7 +165,8 @@ async def asyncio_detailed( **Available Extensions:** - **RoboLedger**: Complete accounting system with XBRL reporting, general ledger, and financial statements - - **RoboInvestor**: Investment portfolio management and tracking + - **RoboInvestor**: Investment portfolio management with securities tracking, trade execution, and + risk analysis - **RoboSCM**: Supply chain management and logistics - **RoboFO**: Front office operations and CRM - **RoboHRM**: Human resources management @@ -214,7 +217,8 @@ async def asyncio( **Available Extensions:** - **RoboLedger**: Complete accounting system with XBRL reporting, general ledger, and financial statements - - **RoboInvestor**: Investment portfolio management and tracking + - **RoboInvestor**: Investment portfolio management with securities tracking, trade execution, and + risk analysis - **RoboSCM**: Supply chain management and logistics - **RoboFO**: Front office operations and CRM - **RoboHRM**: Human resources management diff --git a/robosystems_client/api/views/__init__.py b/robosystems_client/api/views/__init__.py new file mode 100644 index 0000000..2d7c0b2 --- /dev/null +++ b/robosystems_client/api/views/__init__.py @@ -0,0 +1 @@ +"""Contains endpoint functions for accessing the API""" diff --git a/robosystems_client/api/views/create_view.py b/robosystems_client/api/views/create_view.py new file mode 100644 index 0000000..635557b --- /dev/null +++ b/robosystems_client/api/views/create_view.py @@ -0,0 +1,204 @@ +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.create_view_request import CreateViewRequest +from ...models.http_validation_error import HTTPValidationError +from ...types import Response + + +def _get_kwargs( + graph_id: str, + *, + body: CreateViewRequest, +) -> dict[str, Any]: + headers: dict[str, Any] = {} + + _kwargs: dict[str, Any] = { + "method": "post", + "url": "/v1/graphs/{graph_id}/views".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 +) -> Any | HTTPValidationError | None: + if response.status_code == 200: + response_200 = response.json() + return response_200 + + if response.status_code == 422: + response_422 = HTTPValidationError.from_dict(response.json()) + + return response_422 + + 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[Any | HTTPValidationError]: + 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: CreateViewRequest, +) -> Response[Any | HTTPValidationError]: + """Create View + + Build a fact grid from existing facts in the graph. + + Queries Fact nodes by element qnames or canonical concepts, with optional + filters for periods, entities, filing form, fiscal context, and period type. + Returns deduplicated consolidated facts as a pivot table. + + Args: + graph_id (str): + body (CreateViewRequest): + + 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[Any | HTTPValidationError] + """ + + kwargs = _get_kwargs( + graph_id=graph_id, + body=body, + ) + + response = client.get_httpx_client().request( + **kwargs, + ) + + return _build_response(client=client, response=response) + + +def sync( + graph_id: str, + *, + client: AuthenticatedClient, + body: CreateViewRequest, +) -> Any | HTTPValidationError | None: + """Create View + + Build a fact grid from existing facts in the graph. + + Queries Fact nodes by element qnames or canonical concepts, with optional + filters for periods, entities, filing form, fiscal context, and period type. + Returns deduplicated consolidated facts as a pivot table. + + Args: + graph_id (str): + body (CreateViewRequest): + + 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: + Any | HTTPValidationError + """ + + return sync_detailed( + graph_id=graph_id, + client=client, + body=body, + ).parsed + + +async def asyncio_detailed( + graph_id: str, + *, + client: AuthenticatedClient, + body: CreateViewRequest, +) -> Response[Any | HTTPValidationError]: + """Create View + + Build a fact grid from existing facts in the graph. + + Queries Fact nodes by element qnames or canonical concepts, with optional + filters for periods, entities, filing form, fiscal context, and period type. + Returns deduplicated consolidated facts as a pivot table. + + Args: + graph_id (str): + body (CreateViewRequest): + + 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[Any | HTTPValidationError] + """ + + kwargs = _get_kwargs( + graph_id=graph_id, + body=body, + ) + + 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: CreateViewRequest, +) -> Any | HTTPValidationError | None: + """Create View + + Build a fact grid from existing facts in the graph. + + Queries Fact nodes by element qnames or canonical concepts, with optional + filters for periods, entities, filing form, fiscal context, and period type. + Returns deduplicated consolidated facts as a pivot table. + + Args: + graph_id (str): + body (CreateViewRequest): + + 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: + Any | HTTPValidationError + """ + + return ( + await asyncio_detailed( + graph_id=graph_id, + client=client, + body=body, + ) + ).parsed diff --git a/robosystems_client/models/__init__.py b/robosystems_client/models/__init__.py index d9bb93c..306df7d 100644 --- a/robosystems_client/models/__init__.py +++ b/robosystems_client/models/__init__.py @@ -66,6 +66,7 @@ from .create_repository_subscription_request import CreateRepositorySubscriptionRequest from .create_subgraph_request import CreateSubgraphRequest from .create_subgraph_request_metadata_type_0 import CreateSubgraphRequestMetadataType0 +from .create_view_request import CreateViewRequest from .credit_limits import CreditLimits from .credit_summary import CreditSummary from .credit_summary_operation_breakdown import CreditSummaryOperationBreakdown @@ -200,13 +201,6 @@ from .performance_insights import PerformanceInsights from .performance_insights_operation_stats import PerformanceInsightsOperationStats from .performance_insights_slow_queries_item import PerformanceInsightsSlowQueriesItem -from .plaid_connection_config import PlaidConnectionConfig -from .plaid_connection_config_accounts_type_0_item import ( - PlaidConnectionConfigAccountsType0Item, -) -from .plaid_connection_config_institution_type_0 import ( - PlaidConnectionConfigInstitutionType0, -) from .portal_session_response import PortalSessionResponse from .query_limits import QueryLimits from .quick_books_connection_config import QuickBooksConnectionConfig @@ -280,6 +274,10 @@ from .user_response import UserResponse from .validation_error import ValidationError from .validation_error_context import ValidationErrorContext +from .view_axis_config import ViewAxisConfig +from .view_axis_config_element_labels_type_0 import ViewAxisConfigElementLabelsType0 +from .view_axis_config_member_labels_type_0 import ViewAxisConfigMemberLabelsType0 +from .view_config import ViewConfig __all__ = ( "AccountInfo", @@ -340,6 +338,7 @@ "CreateRepositorySubscriptionRequest", "CreateSubgraphRequest", "CreateSubgraphRequestMetadataType0", + "CreateViewRequest", "CreditLimits", "CreditSummary", "CreditSummaryOperationBreakdown", @@ -452,9 +451,6 @@ "PerformanceInsights", "PerformanceInsightsOperationStats", "PerformanceInsightsSlowQueriesItem", - "PlaidConnectionConfig", - "PlaidConnectionConfigAccountsType0Item", - "PlaidConnectionConfigInstitutionType0", "PortalSessionResponse", "QueryLimits", "QuickBooksConnectionConfig", @@ -516,4 +512,8 @@ "UserResponse", "ValidationError", "ValidationErrorContext", + "ViewAxisConfig", + "ViewAxisConfigElementLabelsType0", + "ViewAxisConfigMemberLabelsType0", + "ViewConfig", ) diff --git a/robosystems_client/models/connection_provider_info_provider.py b/robosystems_client/models/connection_provider_info_provider.py index cbe28a5..265571e 100644 --- a/robosystems_client/models/connection_provider_info_provider.py +++ b/robosystems_client/models/connection_provider_info_provider.py @@ -2,7 +2,6 @@ class ConnectionProviderInfoProvider(str, Enum): - PLAID = "plaid" QUICKBOOKS = "quickbooks" SEC = "sec" diff --git a/robosystems_client/models/connection_response.py b/robosystems_client/models/connection_response.py index 3294f42..c5ce7bf 100644 --- a/robosystems_client/models/connection_response.py +++ b/robosystems_client/models/connection_response.py @@ -24,20 +24,20 @@ class ConnectionResponse: Attributes: connection_id (str): Unique connection identifier provider (str): Connection provider type - entity_id (str): Entity identifier status (str): Connection status created_at (datetime.datetime | str): Creation timestamp metadata (ConnectionResponseMetadata): Provider-specific metadata + entity_id (None | str | Unset): Entity identifier updated_at (datetime.datetime | None | str | Unset): Last update timestamp last_sync (datetime.datetime | None | str | Unset): Last sync timestamp """ connection_id: str provider: str - entity_id: str status: str created_at: datetime.datetime | str metadata: ConnectionResponseMetadata + entity_id: None | str | Unset = UNSET updated_at: datetime.datetime | None | str | Unset = UNSET last_sync: datetime.datetime | None | str | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -47,8 +47,6 @@ def to_dict(self) -> dict[str, Any]: provider = self.provider - entity_id = self.entity_id - status = self.status created_at: str @@ -59,6 +57,12 @@ def to_dict(self) -> dict[str, Any]: metadata = self.metadata.to_dict() + entity_id: None | str | Unset + if isinstance(self.entity_id, Unset): + entity_id = UNSET + else: + entity_id = self.entity_id + updated_at: None | str | Unset if isinstance(self.updated_at, Unset): updated_at = UNSET @@ -81,12 +85,13 @@ def to_dict(self) -> dict[str, Any]: { "connection_id": connection_id, "provider": provider, - "entity_id": entity_id, "status": status, "created_at": created_at, "metadata": metadata, } ) + if entity_id is not UNSET: + field_dict["entity_id"] = entity_id if updated_at is not UNSET: field_dict["updated_at"] = updated_at if last_sync is not UNSET: @@ -103,8 +108,6 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: provider = d.pop("provider") - entity_id = d.pop("entity_id") - status = d.pop("status") def _parse_created_at(data: object) -> datetime.datetime | str: @@ -122,6 +125,15 @@ def _parse_created_at(data: object) -> datetime.datetime | str: metadata = ConnectionResponseMetadata.from_dict(d.pop("metadata")) + def _parse_entity_id(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + entity_id = _parse_entity_id(d.pop("entity_id", UNSET)) + def _parse_updated_at(data: object) -> datetime.datetime | None | str | Unset: if data is None: return data @@ -159,10 +171,10 @@ def _parse_last_sync(data: object) -> datetime.datetime | None | str | Unset: connection_response = cls( connection_id=connection_id, provider=provider, - entity_id=entity_id, status=status, created_at=created_at, metadata=metadata, + entity_id=entity_id, updated_at=updated_at, last_sync=last_sync, ) diff --git a/robosystems_client/models/create_connection_request.py b/robosystems_client/models/create_connection_request.py index 645b3b3..d729f09 100644 --- a/robosystems_client/models/create_connection_request.py +++ b/robosystems_client/models/create_connection_request.py @@ -10,7 +10,6 @@ from ..types import UNSET, Unset if TYPE_CHECKING: - from ..models.plaid_connection_config import PlaidConnectionConfig from ..models.quick_books_connection_config import QuickBooksConnectionConfig from ..models.sec_connection_config import SECConnectionConfig @@ -24,27 +23,29 @@ class CreateConnectionRequest: Attributes: provider (CreateConnectionRequestProvider): Connection provider type - entity_id (str): Entity identifier + 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): quickbooks_config (None | QuickBooksConnectionConfig | Unset): - plaid_config (None | PlaidConnectionConfig | Unset): """ provider: CreateConnectionRequestProvider - entity_id: str + entity_id: None | str | Unset = UNSET sec_config: None | SECConnectionConfig | Unset = UNSET quickbooks_config: None | QuickBooksConnectionConfig | Unset = UNSET - plaid_config: None | PlaidConnectionConfig | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: - from ..models.plaid_connection_config import PlaidConnectionConfig from ..models.quick_books_connection_config import QuickBooksConnectionConfig from ..models.sec_connection_config import SECConnectionConfig provider = self.provider.value - entity_id = self.entity_id + entity_id: None | str | Unset + if isinstance(self.entity_id, Unset): + entity_id = UNSET + else: + entity_id = self.entity_id sec_config: dict[str, Any] | None | Unset if isinstance(self.sec_config, Unset): @@ -62,41 +63,38 @@ def to_dict(self) -> dict[str, Any]: else: quickbooks_config = self.quickbooks_config - plaid_config: dict[str, Any] | None | Unset - if isinstance(self.plaid_config, Unset): - plaid_config = UNSET - elif isinstance(self.plaid_config, PlaidConnectionConfig): - plaid_config = self.plaid_config.to_dict() - else: - plaid_config = self.plaid_config - field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( { "provider": provider, - "entity_id": entity_id, } ) + 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 plaid_config is not UNSET: - field_dict["plaid_config"] = plaid_config return field_dict @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - from ..models.plaid_connection_config import PlaidConnectionConfig from ..models.quick_books_connection_config import QuickBooksConnectionConfig from ..models.sec_connection_config import SECConnectionConfig d = dict(src_dict) provider = CreateConnectionRequestProvider(d.pop("provider")) - entity_id = d.pop("entity_id") + def _parse_entity_id(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + entity_id = _parse_entity_id(d.pop("entity_id", UNSET)) def _parse_sec_config(data: object) -> None | SECConnectionConfig | Unset: if data is None: @@ -134,29 +132,11 @@ def _parse_quickbooks_config( quickbooks_config = _parse_quickbooks_config(d.pop("quickbooks_config", UNSET)) - def _parse_plaid_config(data: object) -> None | PlaidConnectionConfig | Unset: - if data is None: - return data - if isinstance(data, Unset): - return data - try: - if not isinstance(data, dict): - raise TypeError() - plaid_config_type_0 = PlaidConnectionConfig.from_dict(data) - - return plaid_config_type_0 - except (TypeError, ValueError, AttributeError, KeyError): - pass - return cast(None | PlaidConnectionConfig | Unset, data) - - plaid_config = _parse_plaid_config(d.pop("plaid_config", UNSET)) - create_connection_request = cls( provider=provider, entity_id=entity_id, sec_config=sec_config, quickbooks_config=quickbooks_config, - plaid_config=plaid_config, ) create_connection_request.additional_properties = d diff --git a/robosystems_client/models/create_connection_request_provider.py b/robosystems_client/models/create_connection_request_provider.py index 0d68faa..9a63ab0 100644 --- a/robosystems_client/models/create_connection_request_provider.py +++ b/robosystems_client/models/create_connection_request_provider.py @@ -2,7 +2,6 @@ class CreateConnectionRequestProvider(str, Enum): - PLAID = "plaid" QUICKBOOKS = "quickbooks" SEC = "sec" diff --git a/robosystems_client/models/create_view_request.py b/robosystems_client/models/create_view_request.py new file mode 100644 index 0000000..d56d1ff --- /dev/null +++ b/robosystems_client/models/create_view_request.py @@ -0,0 +1,228 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.view_config import ViewConfig + + +T = TypeVar("T", bound="CreateViewRequest") + + +@_attrs_define +class CreateViewRequest: + """ + Attributes: + elements (list[str] | Unset): Element qnames (e.g., 'us-gaap:Assets'). Can combine with canonical_concepts. + canonical_concepts (list[str] | Unset): Canonical concept names (e.g., 'revenue', 'net_income'). Matches all + mapped qnames. + periods (list[str] | Unset): Period end dates (YYYY-MM-DD format) + entity (None | str | Unset): Filter by entity ticker, CIK, or name + entities (list[str] | Unset): Filter by multiple entity tickers (e.g., ['NVDA', 'AAPL']) + form (None | str | Unset): Filter by SEC filing form type (e.g., '10-K', '10-Q') + fiscal_year (int | None | Unset): Filter by fiscal year (e.g., 2024) + fiscal_period (None | str | Unset): Filter by fiscal period (e.g., 'FY', 'Q1', 'Q2', 'Q3') + period_type (None | str | Unset): Filter by period type: 'annual', 'quarterly', or 'instant' + include_summary (bool | Unset): Include summary statistics per element Default: False. + view_config (ViewConfig | Unset): + """ + + elements: list[str] | Unset = UNSET + canonical_concepts: list[str] | Unset = UNSET + periods: list[str] | Unset = UNSET + entity: None | str | Unset = UNSET + entities: list[str] | Unset = UNSET + form: None | str | Unset = UNSET + fiscal_year: int | None | Unset = UNSET + fiscal_period: None | str | Unset = UNSET + period_type: None | str | Unset = UNSET + include_summary: bool | Unset = False + view_config: ViewConfig | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + elements: list[str] | Unset = UNSET + if not isinstance(self.elements, Unset): + elements = self.elements + + canonical_concepts: list[str] | Unset = UNSET + if not isinstance(self.canonical_concepts, Unset): + canonical_concepts = self.canonical_concepts + + periods: list[str] | Unset = UNSET + if not isinstance(self.periods, Unset): + periods = self.periods + + entity: None | str | Unset + if isinstance(self.entity, Unset): + entity = UNSET + else: + entity = self.entity + + entities: list[str] | Unset = UNSET + if not isinstance(self.entities, Unset): + entities = self.entities + + form: None | str | Unset + if isinstance(self.form, Unset): + form = UNSET + else: + form = self.form + + fiscal_year: int | None | Unset + if isinstance(self.fiscal_year, Unset): + fiscal_year = UNSET + else: + fiscal_year = self.fiscal_year + + fiscal_period: None | str | Unset + if isinstance(self.fiscal_period, Unset): + fiscal_period = UNSET + else: + fiscal_period = self.fiscal_period + + period_type: None | str | Unset + if isinstance(self.period_type, Unset): + period_type = UNSET + else: + period_type = self.period_type + + include_summary = self.include_summary + + view_config: dict[str, Any] | Unset = UNSET + if not isinstance(self.view_config, Unset): + view_config = self.view_config.to_dict() + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if elements is not UNSET: + field_dict["elements"] = elements + if canonical_concepts is not UNSET: + field_dict["canonical_concepts"] = canonical_concepts + if periods is not UNSET: + field_dict["periods"] = periods + if entity is not UNSET: + field_dict["entity"] = entity + if entities is not UNSET: + field_dict["entities"] = entities + if form is not UNSET: + field_dict["form"] = form + if fiscal_year is not UNSET: + field_dict["fiscal_year"] = fiscal_year + if fiscal_period is not UNSET: + field_dict["fiscal_period"] = fiscal_period + if period_type is not UNSET: + field_dict["period_type"] = period_type + if include_summary is not UNSET: + field_dict["include_summary"] = include_summary + if view_config is not UNSET: + field_dict["view_config"] = view_config + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.view_config import ViewConfig + + d = dict(src_dict) + elements = cast(list[str], d.pop("elements", UNSET)) + + canonical_concepts = cast(list[str], d.pop("canonical_concepts", UNSET)) + + periods = cast(list[str], d.pop("periods", UNSET)) + + def _parse_entity(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + entity = _parse_entity(d.pop("entity", UNSET)) + + entities = cast(list[str], d.pop("entities", UNSET)) + + def _parse_form(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + form = _parse_form(d.pop("form", UNSET)) + + def _parse_fiscal_year(data: object) -> int | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(int | None | Unset, data) + + fiscal_year = _parse_fiscal_year(d.pop("fiscal_year", UNSET)) + + def _parse_fiscal_period(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + fiscal_period = _parse_fiscal_period(d.pop("fiscal_period", UNSET)) + + def _parse_period_type(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + period_type = _parse_period_type(d.pop("period_type", UNSET)) + + include_summary = d.pop("include_summary", UNSET) + + _view_config = d.pop("view_config", UNSET) + view_config: ViewConfig | Unset + if isinstance(_view_config, Unset): + view_config = UNSET + else: + view_config = ViewConfig.from_dict(_view_config) + + create_view_request = cls( + elements=elements, + canonical_concepts=canonical_concepts, + periods=periods, + entity=entity, + entities=entities, + form=form, + fiscal_year=fiscal_year, + fiscal_period=fiscal_period, + period_type=period_type, + include_summary=include_summary, + view_config=view_config, + ) + + create_view_request.additional_properties = d + return create_view_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/list_connections_provider_type_0.py b/robosystems_client/models/list_connections_provider_type_0.py index 7c20ede..9b93356 100644 --- a/robosystems_client/models/list_connections_provider_type_0.py +++ b/robosystems_client/models/list_connections_provider_type_0.py @@ -2,7 +2,6 @@ class ListConnectionsProviderType0(str, Enum): - PLAID = "plaid" QUICKBOOKS = "quickbooks" SEC = "sec" diff --git a/robosystems_client/models/plaid_connection_config.py b/robosystems_client/models/plaid_connection_config.py deleted file mode 100644 index 2922cac..0000000 --- a/robosystems_client/models/plaid_connection_config.py +++ /dev/null @@ -1,209 +0,0 @@ -from __future__ import annotations - -from collections.abc import Mapping -from typing import TYPE_CHECKING, Any, TypeVar, cast - -from attrs import define as _attrs_define -from attrs import field as _attrs_field - -from ..types import UNSET, Unset - -if TYPE_CHECKING: - from ..models.plaid_connection_config_accounts_type_0_item import ( - PlaidConnectionConfigAccountsType0Item, - ) - from ..models.plaid_connection_config_institution_type_0 import ( - PlaidConnectionConfigInstitutionType0, - ) - - -T = TypeVar("T", bound="PlaidConnectionConfig") - - -@_attrs_define -class PlaidConnectionConfig: - """Plaid-specific connection configuration. - - Attributes: - public_token (None | str | Unset): Plaid public token for exchange - access_token (None | str | Unset): Plaid access token (set after exchange) - item_id (None | str | Unset): Plaid item ID - institution (None | PlaidConnectionConfigInstitutionType0 | Unset): Institution information - accounts (list[PlaidConnectionConfigAccountsType0Item] | None | Unset): Connected accounts - """ - - public_token: None | str | Unset = UNSET - access_token: None | str | Unset = UNSET - item_id: None | str | Unset = UNSET - institution: None | PlaidConnectionConfigInstitutionType0 | Unset = UNSET - accounts: list[PlaidConnectionConfigAccountsType0Item] | None | Unset = UNSET - additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) - - def to_dict(self) -> dict[str, Any]: - from ..models.plaid_connection_config_institution_type_0 import ( - PlaidConnectionConfigInstitutionType0, - ) - - public_token: None | str | Unset - if isinstance(self.public_token, Unset): - public_token = UNSET - else: - public_token = self.public_token - - access_token: None | str | Unset - if isinstance(self.access_token, Unset): - access_token = UNSET - else: - access_token = self.access_token - - item_id: None | str | Unset - if isinstance(self.item_id, Unset): - item_id = UNSET - else: - item_id = self.item_id - - institution: dict[str, Any] | None | Unset - if isinstance(self.institution, Unset): - institution = UNSET - elif isinstance(self.institution, PlaidConnectionConfigInstitutionType0): - institution = self.institution.to_dict() - else: - institution = self.institution - - accounts: list[dict[str, Any]] | None | Unset - if isinstance(self.accounts, Unset): - accounts = UNSET - elif isinstance(self.accounts, list): - accounts = [] - for accounts_type_0_item_data in self.accounts: - accounts_type_0_item = accounts_type_0_item_data.to_dict() - accounts.append(accounts_type_0_item) - - else: - accounts = self.accounts - - field_dict: dict[str, Any] = {} - field_dict.update(self.additional_properties) - field_dict.update({}) - if public_token is not UNSET: - field_dict["public_token"] = public_token - if access_token is not UNSET: - field_dict["access_token"] = access_token - if item_id is not UNSET: - field_dict["item_id"] = item_id - if institution is not UNSET: - field_dict["institution"] = institution - if accounts is not UNSET: - field_dict["accounts"] = accounts - - return field_dict - - @classmethod - def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - from ..models.plaid_connection_config_accounts_type_0_item import ( - PlaidConnectionConfigAccountsType0Item, - ) - from ..models.plaid_connection_config_institution_type_0 import ( - PlaidConnectionConfigInstitutionType0, - ) - - d = dict(src_dict) - - def _parse_public_token(data: object) -> None | str | Unset: - if data is None: - return data - if isinstance(data, Unset): - return data - return cast(None | str | Unset, data) - - public_token = _parse_public_token(d.pop("public_token", UNSET)) - - def _parse_access_token(data: object) -> None | str | Unset: - if data is None: - return data - if isinstance(data, Unset): - return data - return cast(None | str | Unset, data) - - access_token = _parse_access_token(d.pop("access_token", UNSET)) - - def _parse_item_id(data: object) -> None | str | Unset: - if data is None: - return data - if isinstance(data, Unset): - return data - return cast(None | str | Unset, data) - - item_id = _parse_item_id(d.pop("item_id", UNSET)) - - def _parse_institution( - data: object, - ) -> None | PlaidConnectionConfigInstitutionType0 | Unset: - if data is None: - return data - if isinstance(data, Unset): - return data - try: - if not isinstance(data, dict): - raise TypeError() - institution_type_0 = PlaidConnectionConfigInstitutionType0.from_dict(data) - - return institution_type_0 - except (TypeError, ValueError, AttributeError, KeyError): - pass - return cast(None | PlaidConnectionConfigInstitutionType0 | Unset, data) - - institution = _parse_institution(d.pop("institution", UNSET)) - - def _parse_accounts( - data: object, - ) -> list[PlaidConnectionConfigAccountsType0Item] | None | Unset: - if data is None: - return data - if isinstance(data, Unset): - return data - try: - if not isinstance(data, list): - raise TypeError() - accounts_type_0 = [] - _accounts_type_0 = data - for accounts_type_0_item_data in _accounts_type_0: - accounts_type_0_item = PlaidConnectionConfigAccountsType0Item.from_dict( - accounts_type_0_item_data - ) - - accounts_type_0.append(accounts_type_0_item) - - return accounts_type_0 - except (TypeError, ValueError, AttributeError, KeyError): - pass - return cast(list[PlaidConnectionConfigAccountsType0Item] | None | Unset, data) - - accounts = _parse_accounts(d.pop("accounts", UNSET)) - - plaid_connection_config = cls( - public_token=public_token, - access_token=access_token, - item_id=item_id, - institution=institution, - accounts=accounts, - ) - - plaid_connection_config.additional_properties = d - return plaid_connection_config - - @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/sec_connection_config.py b/robosystems_client/models/sec_connection_config.py index cea8f3f..9b114ee 100644 --- a/robosystems_client/models/sec_connection_config.py +++ b/robosystems_client/models/sec_connection_config.py @@ -1,13 +1,11 @@ from __future__ import annotations from collections.abc import Mapping -from typing import Any, TypeVar, cast +from typing import Any, TypeVar from attrs import define as _attrs_define from attrs import field as _attrs_field -from ..types import UNSET, Unset - T = TypeVar("T", bound="SECConnectionConfig") @@ -16,23 +14,15 @@ class SECConnectionConfig: """SEC-specific connection configuration. Attributes: - cik (str): 10-digit CIK number - entity_name (None | str | Unset): Entity name from SEC + cik (str): SEC Central Index Key """ cik: str - entity_name: None | str | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: cik = self.cik - entity_name: None | str | Unset - if isinstance(self.entity_name, Unset): - entity_name = UNSET - else: - entity_name = self.entity_name - field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update( @@ -40,8 +30,6 @@ def to_dict(self) -> dict[str, Any]: "cik": cik, } ) - if entity_name is not UNSET: - field_dict["entity_name"] = entity_name return field_dict @@ -50,18 +38,8 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) cik = d.pop("cik") - def _parse_entity_name(data: object) -> None | str | Unset: - if data is None: - return data - if isinstance(data, Unset): - return data - return cast(None | str | Unset, data) - - entity_name = _parse_entity_name(d.pop("entity_name", UNSET)) - sec_connection_config = cls( cik=cik, - entity_name=entity_name, ) sec_connection_config.additional_properties = d diff --git a/robosystems_client/models/view_axis_config.py b/robosystems_client/models/view_axis_config.py new file mode 100644 index 0000000..e24c43d --- /dev/null +++ b/robosystems_client/models/view_axis_config.py @@ -0,0 +1,276 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar, cast + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.view_axis_config_element_labels_type_0 import ( + ViewAxisConfigElementLabelsType0, + ) + from ..models.view_axis_config_member_labels_type_0 import ( + ViewAxisConfigMemberLabelsType0, + ) + + +T = TypeVar("T", bound="ViewAxisConfig") + + +@_attrs_define +class ViewAxisConfig: + """ + Attributes: + type_ (str): Axis type: 'element', 'period', 'dimension', 'entity' + dimension_axis (None | str | Unset): Dimension axis name for dimension-type axes + include_null_dimension (bool | Unset): Include facts where this dimension is NULL (default: false) Default: + False. + selected_members (list[str] | None | Unset): Specific members to include (e.g., ['2024-12-31', '2023-12-31']) + member_order (list[str] | None | Unset): Explicit ordering of members (overrides default sort) + member_labels (None | Unset | ViewAxisConfigMemberLabelsType0): Custom labels for members (e.g., {'2024-12-31': + 'Current Year'}) + element_order (list[str] | None | Unset): Element ordering for hierarchy display (e.g., ['us-gaap:Assets', 'us- + gaap:Cash', ...]) + element_labels (None | Unset | ViewAxisConfigElementLabelsType0): Custom labels for elements (e.g., {'us- + gaap:Cash': 'Cash and Cash Equivalents'}) + """ + + type_: str + dimension_axis: None | str | Unset = UNSET + include_null_dimension: bool | Unset = False + selected_members: list[str] | None | Unset = UNSET + member_order: list[str] | None | Unset = UNSET + member_labels: None | Unset | ViewAxisConfigMemberLabelsType0 = UNSET + element_order: list[str] | None | Unset = UNSET + element_labels: None | Unset | ViewAxisConfigElementLabelsType0 = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + from ..models.view_axis_config_element_labels_type_0 import ( + ViewAxisConfigElementLabelsType0, + ) + from ..models.view_axis_config_member_labels_type_0 import ( + ViewAxisConfigMemberLabelsType0, + ) + + type_ = self.type_ + + dimension_axis: None | str | Unset + if isinstance(self.dimension_axis, Unset): + dimension_axis = UNSET + else: + dimension_axis = self.dimension_axis + + include_null_dimension = self.include_null_dimension + + selected_members: list[str] | None | Unset + if isinstance(self.selected_members, Unset): + selected_members = UNSET + elif isinstance(self.selected_members, list): + selected_members = self.selected_members + + else: + selected_members = self.selected_members + + member_order: list[str] | None | Unset + if isinstance(self.member_order, Unset): + member_order = UNSET + elif isinstance(self.member_order, list): + member_order = self.member_order + + else: + member_order = self.member_order + + member_labels: dict[str, Any] | None | Unset + if isinstance(self.member_labels, Unset): + member_labels = UNSET + elif isinstance(self.member_labels, ViewAxisConfigMemberLabelsType0): + member_labels = self.member_labels.to_dict() + else: + member_labels = self.member_labels + + element_order: list[str] | None | Unset + if isinstance(self.element_order, Unset): + element_order = UNSET + elif isinstance(self.element_order, list): + element_order = self.element_order + + else: + element_order = self.element_order + + element_labels: dict[str, Any] | None | Unset + if isinstance(self.element_labels, Unset): + element_labels = UNSET + elif isinstance(self.element_labels, ViewAxisConfigElementLabelsType0): + element_labels = self.element_labels.to_dict() + else: + element_labels = self.element_labels + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update( + { + "type": type_, + } + ) + if dimension_axis is not UNSET: + field_dict["dimension_axis"] = dimension_axis + if include_null_dimension is not UNSET: + field_dict["include_null_dimension"] = include_null_dimension + if selected_members is not UNSET: + field_dict["selected_members"] = selected_members + if member_order is not UNSET: + field_dict["member_order"] = member_order + if member_labels is not UNSET: + field_dict["member_labels"] = member_labels + if element_order is not UNSET: + field_dict["element_order"] = element_order + if element_labels is not UNSET: + field_dict["element_labels"] = element_labels + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.view_axis_config_element_labels_type_0 import ( + ViewAxisConfigElementLabelsType0, + ) + from ..models.view_axis_config_member_labels_type_0 import ( + ViewAxisConfigMemberLabelsType0, + ) + + d = dict(src_dict) + type_ = d.pop("type") + + def _parse_dimension_axis(data: object) -> None | str | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + return cast(None | str | Unset, data) + + dimension_axis = _parse_dimension_axis(d.pop("dimension_axis", UNSET)) + + include_null_dimension = d.pop("include_null_dimension", UNSET) + + def _parse_selected_members(data: object) -> list[str] | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, list): + raise TypeError() + selected_members_type_0 = cast(list[str], data) + + return selected_members_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(list[str] | None | Unset, data) + + selected_members = _parse_selected_members(d.pop("selected_members", UNSET)) + + def _parse_member_order(data: object) -> list[str] | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, list): + raise TypeError() + member_order_type_0 = cast(list[str], data) + + return member_order_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(list[str] | None | Unset, data) + + member_order = _parse_member_order(d.pop("member_order", UNSET)) + + def _parse_member_labels( + data: object, + ) -> None | Unset | ViewAxisConfigMemberLabelsType0: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + member_labels_type_0 = ViewAxisConfigMemberLabelsType0.from_dict(data) + + return member_labels_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(None | Unset | ViewAxisConfigMemberLabelsType0, data) + + member_labels = _parse_member_labels(d.pop("member_labels", UNSET)) + + def _parse_element_order(data: object) -> list[str] | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, list): + raise TypeError() + element_order_type_0 = cast(list[str], data) + + return element_order_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(list[str] | None | Unset, data) + + element_order = _parse_element_order(d.pop("element_order", UNSET)) + + def _parse_element_labels( + data: object, + ) -> None | Unset | ViewAxisConfigElementLabelsType0: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + element_labels_type_0 = ViewAxisConfigElementLabelsType0.from_dict(data) + + return element_labels_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(None | Unset | ViewAxisConfigElementLabelsType0, data) + + element_labels = _parse_element_labels(d.pop("element_labels", UNSET)) + + view_axis_config = cls( + type_=type_, + dimension_axis=dimension_axis, + include_null_dimension=include_null_dimension, + selected_members=selected_members, + member_order=member_order, + member_labels=member_labels, + element_order=element_order, + element_labels=element_labels, + ) + + view_axis_config.additional_properties = d + return view_axis_config + + @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/plaid_connection_config_institution_type_0.py b/robosystems_client/models/view_axis_config_element_labels_type_0.py similarity index 65% rename from robosystems_client/models/plaid_connection_config_institution_type_0.py rename to robosystems_client/models/view_axis_config_element_labels_type_0.py index 15953cb..8f1638f 100644 --- a/robosystems_client/models/plaid_connection_config_institution_type_0.py +++ b/robosystems_client/models/view_axis_config_element_labels_type_0.py @@ -6,14 +6,14 @@ from attrs import define as _attrs_define from attrs import field as _attrs_field -T = TypeVar("T", bound="PlaidConnectionConfigInstitutionType0") +T = TypeVar("T", bound="ViewAxisConfigElementLabelsType0") @_attrs_define -class PlaidConnectionConfigInstitutionType0: +class ViewAxisConfigElementLabelsType0: """ """ - additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + additional_properties: dict[str, str] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: field_dict: dict[str, Any] = {} @@ -24,19 +24,19 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) - plaid_connection_config_institution_type_0 = cls() + view_axis_config_element_labels_type_0 = cls() - plaid_connection_config_institution_type_0.additional_properties = d - return plaid_connection_config_institution_type_0 + view_axis_config_element_labels_type_0.additional_properties = d + return view_axis_config_element_labels_type_0 @property def additional_keys(self) -> list[str]: return list(self.additional_properties.keys()) - def __getitem__(self, key: str) -> Any: + def __getitem__(self, key: str) -> str: return self.additional_properties[key] - def __setitem__(self, key: str, value: Any) -> None: + def __setitem__(self, key: str, value: str) -> None: self.additional_properties[key] = value def __delitem__(self, key: str) -> None: diff --git a/robosystems_client/models/plaid_connection_config_accounts_type_0_item.py b/robosystems_client/models/view_axis_config_member_labels_type_0.py similarity index 65% rename from robosystems_client/models/plaid_connection_config_accounts_type_0_item.py rename to robosystems_client/models/view_axis_config_member_labels_type_0.py index a98cbb5..ec29942 100644 --- a/robosystems_client/models/plaid_connection_config_accounts_type_0_item.py +++ b/robosystems_client/models/view_axis_config_member_labels_type_0.py @@ -6,14 +6,14 @@ from attrs import define as _attrs_define from attrs import field as _attrs_field -T = TypeVar("T", bound="PlaidConnectionConfigAccountsType0Item") +T = TypeVar("T", bound="ViewAxisConfigMemberLabelsType0") @_attrs_define -class PlaidConnectionConfigAccountsType0Item: +class ViewAxisConfigMemberLabelsType0: """ """ - additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + additional_properties: dict[str, str] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: field_dict: dict[str, Any] = {} @@ -24,19 +24,19 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) - plaid_connection_config_accounts_type_0_item = cls() + view_axis_config_member_labels_type_0 = cls() - plaid_connection_config_accounts_type_0_item.additional_properties = d - return plaid_connection_config_accounts_type_0_item + view_axis_config_member_labels_type_0.additional_properties = d + return view_axis_config_member_labels_type_0 @property def additional_keys(self) -> list[str]: return list(self.additional_properties.keys()) - def __getitem__(self, key: str) -> Any: + def __getitem__(self, key: str) -> str: return self.additional_properties[key] - def __setitem__(self, key: str, value: Any) -> None: + def __setitem__(self, key: str, value: str) -> None: self.additional_properties[key] = value def __delitem__(self, key: str) -> None: diff --git a/robosystems_client/models/view_config.py b/robosystems_client/models/view_config.py new file mode 100644 index 0000000..782f103 --- /dev/null +++ b/robosystems_client/models/view_config.py @@ -0,0 +1,127 @@ +from __future__ import annotations + +from collections.abc import Mapping +from typing import TYPE_CHECKING, Any, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.view_axis_config import ViewAxisConfig + + +T = TypeVar("T", bound="ViewConfig") + + +@_attrs_define +class ViewConfig: + """ + Attributes: + rows (list[ViewAxisConfig] | Unset): Row axis configuration + columns (list[ViewAxisConfig] | Unset): Column axis configuration + values (str | Unset): Field to use for values (default: numeric_value) Default: 'numeric_value'. + aggregation_function (str | Unset): Aggregation function: sum, average, count Default: 'sum'. + fill_value (float | Unset): Value to use for missing data Default: 0.0. + """ + + rows: list[ViewAxisConfig] | Unset = UNSET + columns: list[ViewAxisConfig] | Unset = UNSET + values: str | Unset = "numeric_value" + aggregation_function: str | Unset = "sum" + fill_value: float | Unset = 0.0 + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> dict[str, Any]: + rows: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.rows, Unset): + rows = [] + for rows_item_data in self.rows: + rows_item = rows_item_data.to_dict() + rows.append(rows_item) + + columns: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.columns, Unset): + columns = [] + for columns_item_data in self.columns: + columns_item = columns_item_data.to_dict() + columns.append(columns_item) + + values = self.values + + aggregation_function = self.aggregation_function + + fill_value = self.fill_value + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if rows is not UNSET: + field_dict["rows"] = rows + if columns is not UNSET: + field_dict["columns"] = columns + if values is not UNSET: + field_dict["values"] = values + if aggregation_function is not UNSET: + field_dict["aggregation_function"] = aggregation_function + if fill_value is not UNSET: + field_dict["fill_value"] = fill_value + + return field_dict + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.view_axis_config import ViewAxisConfig + + d = dict(src_dict) + _rows = d.pop("rows", UNSET) + rows: list[ViewAxisConfig] | Unset = UNSET + if _rows is not UNSET: + rows = [] + for rows_item_data in _rows: + rows_item = ViewAxisConfig.from_dict(rows_item_data) + + rows.append(rows_item) + + _columns = d.pop("columns", UNSET) + columns: list[ViewAxisConfig] | Unset = UNSET + if _columns is not UNSET: + columns = [] + for columns_item_data in _columns: + columns_item = ViewAxisConfig.from_dict(columns_item_data) + + columns.append(columns_item) + + values = d.pop("values", UNSET) + + aggregation_function = d.pop("aggregation_function", UNSET) + + fill_value = d.pop("fill_value", UNSET) + + view_config = cls( + rows=rows, + columns=columns, + values=values, + aggregation_function=aggregation_function, + fill_value=fill_value, + ) + + view_config.additional_properties = d + return view_config + + @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