robosystems-client 0.2.15__py3-none-any.whl → 0.2.16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of robosystems-client might be problematic. Click here for more details.
- robosystems_client/api/agent/auto_select_agent.py +23 -27
- robosystems_client/api/agent/batch_process_queries.py +13 -13
- robosystems_client/api/agent/execute_specific_agent.py +23 -27
- robosystems_client/api/agent/get_agent_metadata.py +13 -13
- robosystems_client/api/agent/list_agents.py +23 -23
- robosystems_client/api/agent/recommend_agent.py +13 -13
- robosystems_client/api/auth/check_password_strength.py +17 -17
- robosystems_client/api/auth/complete_sso_auth.py +17 -17
- robosystems_client/api/auth/forgot_password.py +17 -23
- robosystems_client/api/auth/generate_sso_token.py +26 -26
- robosystems_client/api/auth/get_captcha_config.py +6 -6
- robosystems_client/api/auth/get_current_auth_user.py +17 -17
- robosystems_client/api/auth/get_password_policy.py +10 -10
- robosystems_client/api/auth/login_user.py +17 -17
- robosystems_client/api/auth/logout_user.py +10 -10
- robosystems_client/api/auth/refresh_auth_session.py +17 -17
- robosystems_client/api/auth/register_user.py +17 -17
- robosystems_client/api/auth/resend_verification_email.py +17 -29
- robosystems_client/api/auth/reset_password.py +17 -17
- robosystems_client/api/auth/sso_token_exchange.py +17 -17
- robosystems_client/api/auth/validate_reset_token.py +17 -17
- robosystems_client/api/auth/verify_email.py +17 -17
- robosystems_client/api/backup/create_backup.py +13 -13
- robosystems_client/api/backup/get_backup_download_url.py +22 -22
- robosystems_client/api/backup/get_backup_stats.py +13 -13
- robosystems_client/api/backup/list_backups.py +31 -31
- robosystems_client/api/backup/restore_backup.py +13 -13
- robosystems_client/api/billing/cancel_org_subscription.py +13 -13
- robosystems_client/api/billing/create_checkout_session.py +13 -13
- robosystems_client/api/billing/create_portal_session.py +13 -13
- robosystems_client/api/billing/get_checkout_status.py +13 -13
- robosystems_client/api/billing/get_org_billing_customer.py +13 -13
- robosystems_client/api/billing/get_org_subscription.py +13 -13
- robosystems_client/api/billing/get_org_upcoming_invoice.py +16 -16
- robosystems_client/api/billing/list_org_invoices.py +22 -22
- robosystems_client/api/billing/list_org_subscriptions.py +13 -13
- robosystems_client/api/connections/create_connection.py +13 -13
- robosystems_client/api/connections/create_link_token.py +13 -13
- robosystems_client/api/connections/delete_connection.py +13 -13
- robosystems_client/api/connections/exchange_link_token.py +13 -13
- robosystems_client/api/connections/get_connection.py +13 -13
- robosystems_client/api/connections/get_connection_options.py +13 -13
- robosystems_client/api/connections/init_o_auth.py +13 -13
- robosystems_client/api/connections/list_connections.py +33 -33
- robosystems_client/api/connections/oauth_callback.py +13 -13
- robosystems_client/api/connections/sync_connection.py +13 -19
- robosystems_client/api/credits_/check_credit_balance.py +38 -45
- robosystems_client/api/credits_/check_storage_limits.py +13 -13
- robosystems_client/api/credits_/get_credit_summary.py +13 -13
- robosystems_client/api/credits_/get_storage_usage.py +28 -28
- robosystems_client/api/credits_/list_credit_transactions.py +71 -71
- robosystems_client/api/files/__init__.py +1 -0
- robosystems_client/api/files/create_file_upload.py +311 -0
- robosystems_client/api/files/delete_file.py +354 -0
- robosystems_client/api/files/get_file.py +329 -0
- robosystems_client/api/files/list_files.py +346 -0
- robosystems_client/api/files/update_file.py +320 -0
- robosystems_client/api/graph_health/get_database_health.py +13 -13
- robosystems_client/api/graph_info/get_database_info.py +13 -13
- robosystems_client/api/graph_limits/get_graph_limits.py +13 -13
- robosystems_client/api/graphs/create_graph.py +13 -13
- robosystems_client/api/graphs/get_available_extensions.py +13 -13
- robosystems_client/api/graphs/get_available_graph_tiers.py +22 -22
- robosystems_client/api/graphs/get_graphs.py +13 -13
- robosystems_client/api/graphs/select_graph.py +13 -13
- robosystems_client/api/materialization/__init__.py +1 -0
- robosystems_client/api/materialization/get_materialization_status.py +272 -0
- robosystems_client/api/materialization/materialize_graph.py +416 -0
- robosystems_client/api/mcp/call_mcp_tool.py +32 -32
- robosystems_client/api/mcp/list_mcp_tools.py +13 -13
- robosystems_client/api/operations/cancel_operation.py +13 -13
- robosystems_client/api/operations/get_operation_status.py +13 -25
- robosystems_client/api/operations/stream_operation_events.py +41 -41
- robosystems_client/api/org/create_org.py +13 -13
- robosystems_client/api/org/get_org.py +13 -13
- robosystems_client/api/org/list_org_graphs.py +13 -13
- robosystems_client/api/org/list_user_orgs.py +6 -6
- robosystems_client/api/org/update_org.py +13 -13
- robosystems_client/api/org_members/invite_org_member.py +13 -13
- robosystems_client/api/org_members/list_org_members.py +13 -13
- robosystems_client/api/org_members/remove_org_member.py +13 -13
- robosystems_client/api/org_members/update_org_member_role.py +13 -13
- robosystems_client/api/org_usage/get_org_limits.py +13 -13
- robosystems_client/api/org_usage/get_org_usage.py +22 -22
- robosystems_client/api/query/execute_cypher_query.py +74 -62
- robosystems_client/api/schema/export_graph_schema.py +35 -35
- robosystems_client/api/schema/get_graph_schema.py +13 -13
- robosystems_client/api/schema/validate_schema.py +13 -13
- robosystems_client/api/service_offerings/get_service_offerings.py +17 -17
- robosystems_client/api/status/get_service_status.py +10 -10
- robosystems_client/api/subgraphs/create_subgraph.py +64 -28
- robosystems_client/api/subgraphs/delete_subgraph.py +13 -13
- robosystems_client/api/subgraphs/get_subgraph_info.py +13 -13
- robosystems_client/api/subgraphs/get_subgraph_quota.py +13 -13
- robosystems_client/api/subgraphs/list_subgraphs.py +13 -13
- robosystems_client/api/subscriptions/create_repository_subscription.py +13 -13
- robosystems_client/api/subscriptions/get_graph_subscription.py +13 -13
- robosystems_client/api/subscriptions/upgrade_subscription.py +13 -13
- robosystems_client/api/tables/list_tables.py +13 -13
- robosystems_client/api/tables/query_tables.py +13 -13
- robosystems_client/api/usage/get_graph_metrics.py +13 -13
- robosystems_client/api/usage/get_graph_usage_analytics.py +66 -66
- robosystems_client/api/user/create_user_api_key.py +13 -13
- robosystems_client/api/user/get_current_user.py +6 -6
- robosystems_client/api/user/list_user_api_keys.py +6 -6
- robosystems_client/api/user/revoke_user_api_key.py +13 -13
- robosystems_client/api/user/update_user.py +13 -13
- robosystems_client/api/user/update_user_api_key.py +13 -13
- robosystems_client/api/user/update_user_password.py +13 -13
- robosystems_client/api/views/__init__.py +1 -0
- robosystems_client/api/views/create_view.py +245 -0
- robosystems_client/api/views/save_view.py +299 -0
- robosystems_client/client.py +13 -13
- robosystems_client/extensions/__init__.py +39 -0
- robosystems_client/extensions/element_mapping_client.py +585 -0
- robosystems_client/extensions/subgraph_workspace_client.py +744 -0
- robosystems_client/extensions/table_ingest_client.py +24 -23
- robosystems_client/extensions/view_builder_client.py +617 -0
- robosystems_client/models/__init__.py +34 -10
- robosystems_client/models/account_info.py +2 -0
- robosystems_client/models/agent_list_response.py +3 -1
- robosystems_client/models/agent_list_response_agents.py +5 -3
- robosystems_client/models/agent_list_response_agents_additional_property.py +2 -0
- robosystems_client/models/agent_message.py +9 -7
- robosystems_client/models/agent_metadata_response.py +11 -9
- robosystems_client/models/agent_recommendation.py +8 -6
- robosystems_client/models/agent_recommendation_request.py +9 -7
- robosystems_client/models/agent_recommendation_request_context_type_0.py +2 -0
- robosystems_client/models/agent_recommendation_response.py +4 -2
- robosystems_client/models/agent_request.py +41 -40
- robosystems_client/models/agent_request_context_type_0.py +2 -0
- robosystems_client/models/agent_response.py +42 -44
- robosystems_client/models/agent_response_error_details_type_0.py +2 -0
- robosystems_client/models/agent_response_metadata_type_0.py +2 -0
- robosystems_client/models/agent_response_tokens_used_type_0.py +2 -0
- robosystems_client/models/api_key_info.py +18 -16
- robosystems_client/models/api_keys_response.py +4 -2
- robosystems_client/models/auth_response.py +26 -24
- robosystems_client/models/auth_response_org_type_0.py +2 -0
- robosystems_client/models/auth_response_user.py +2 -0
- robosystems_client/models/available_extension.py +5 -3
- robosystems_client/models/available_extensions_response.py +4 -2
- robosystems_client/models/available_graph_tiers_response.py +4 -2
- robosystems_client/models/backup_create_request.py +18 -16
- robosystems_client/models/backup_download_url_response.py +2 -0
- robosystems_client/models/backup_limits.py +2 -0
- robosystems_client/models/backup_list_response.py +4 -2
- robosystems_client/models/backup_response.py +13 -11
- robosystems_client/models/backup_restore_request.py +7 -6
- robosystems_client/models/backup_stats_response.py +9 -7
- robosystems_client/models/backup_stats_response_backup_formats.py +2 -0
- robosystems_client/models/batch_agent_request.py +7 -5
- robosystems_client/models/batch_agent_response.py +4 -2
- robosystems_client/models/billing_customer.py +10 -8
- robosystems_client/models/cancel_operation_response_canceloperation.py +2 -0
- robosystems_client/models/check_credit_balance_response_checkcreditbalance.py +2 -0
- robosystems_client/models/checkout_response.py +22 -20
- robosystems_client/models/checkout_status_response.py +19 -17
- robosystems_client/models/connection_options_response.py +4 -2
- robosystems_client/models/connection_provider_info.py +26 -24
- robosystems_client/models/connection_response.py +14 -12
- robosystems_client/models/connection_response_metadata.py +2 -0
- robosystems_client/models/copy_operation_limits.py +2 -0
- robosystems_client/models/create_api_key_request.py +13 -11
- robosystems_client/models/create_api_key_response.py +3 -1
- robosystems_client/models/create_checkout_request.py +3 -1
- robosystems_client/models/create_checkout_request_resource_config.py +2 -0
- robosystems_client/models/create_connection_request.py +21 -21
- robosystems_client/models/create_graph_request.py +25 -25
- robosystems_client/models/create_org_request.py +7 -5
- robosystems_client/models/create_repository_subscription_request.py +2 -0
- robosystems_client/models/create_subgraph_request.py +30 -19
- robosystems_client/models/create_subgraph_request_metadata_type_0.py +2 -0
- robosystems_client/models/create_view_request.py +141 -0
- robosystems_client/models/credit_limits.py +2 -0
- robosystems_client/models/credit_summary.py +3 -1
- robosystems_client/models/credit_summary_operation_breakdown.py +2 -0
- robosystems_client/models/credit_summary_response.py +8 -6
- robosystems_client/models/custom_schema_definition.py +39 -33
- robosystems_client/models/custom_schema_definition_metadata.py +2 -0
- robosystems_client/models/custom_schema_definition_nodes_item.py +2 -0
- robosystems_client/models/custom_schema_definition_relationships_item.py +2 -0
- robosystems_client/models/cypher_query_request.py +15 -13
- robosystems_client/models/cypher_query_request_parameters_type_0.py +2 -0
- robosystems_client/models/database_health_response.py +21 -19
- robosystems_client/models/database_info_response.py +13 -11
- robosystems_client/models/delete_file_response.py +54 -1
- robosystems_client/models/delete_subgraph_request.py +12 -10
- robosystems_client/models/delete_subgraph_response.py +13 -11
- robosystems_client/models/detailed_transactions_response.py +6 -4
- robosystems_client/models/detailed_transactions_response_date_range.py +2 -0
- robosystems_client/models/detailed_transactions_response_summary.py +5 -3
- robosystems_client/models/email_verification_request.py +2 -0
- robosystems_client/models/enhanced_credit_transaction_response.py +24 -22
- robosystems_client/models/enhanced_credit_transaction_response_metadata.py +2 -0
- robosystems_client/models/enhanced_file_status_layers.py +83 -0
- robosystems_client/models/error_response.py +19 -17
- robosystems_client/models/exchange_token_request.py +9 -7
- robosystems_client/models/exchange_token_request_metadata_type_0.py +2 -0
- robosystems_client/models/execute_cypher_query_response_200.py +25 -21
- robosystems_client/models/execute_cypher_query_response_200_data_item.py +2 -0
- robosystems_client/models/fact_detail.py +109 -0
- robosystems_client/models/file_info.py +18 -16
- robosystems_client/models/file_layer_status.py +123 -0
- robosystems_client/models/file_status_update.py +14 -0
- robosystems_client/models/file_upload_request.py +25 -3
- robosystems_client/models/file_upload_response.py +2 -0
- robosystems_client/models/forgot_password_request.py +2 -0
- robosystems_client/models/forgot_password_response_forgotpassword.py +2 -0
- robosystems_client/models/get_current_auth_user_response_getcurrentauthuser.py +2 -0
- robosystems_client/models/get_file_info_response.py +62 -21
- robosystems_client/models/get_operation_status_response_getoperationstatus.py +2 -0
- robosystems_client/models/get_storage_usage_response_getstorageusage.py +2 -0
- robosystems_client/models/graph_info.py +10 -8
- robosystems_client/models/graph_limits_response.py +14 -12
- robosystems_client/models/graph_metadata.py +14 -12
- robosystems_client/models/graph_metrics_response.py +17 -15
- robosystems_client/models/graph_metrics_response_estimated_size.py +2 -0
- robosystems_client/models/graph_metrics_response_health_status.py +2 -0
- robosystems_client/models/graph_metrics_response_node_counts.py +2 -0
- robosystems_client/models/graph_metrics_response_relationship_counts.py +2 -0
- robosystems_client/models/graph_subscription_response.py +28 -26
- robosystems_client/models/graph_subscription_tier.py +15 -13
- robosystems_client/models/graph_subscriptions.py +5 -3
- robosystems_client/models/graph_tier_backup.py +2 -0
- robosystems_client/models/graph_tier_copy_operations.py +2 -0
- robosystems_client/models/graph_tier_info.py +15 -13
- robosystems_client/models/graph_tier_instance.py +2 -0
- robosystems_client/models/graph_tier_limits.py +10 -8
- robosystems_client/models/graph_usage_response.py +32 -30
- robosystems_client/models/graph_usage_response_recent_events_item.py +2 -0
- robosystems_client/models/health_status.py +9 -7
- robosystems_client/models/health_status_details_type_0.py +2 -0
- robosystems_client/models/http_validation_error.py +12 -8
- robosystems_client/models/initial_entity_data.py +38 -36
- robosystems_client/models/invite_member_request.py +9 -7
- robosystems_client/models/invoice.py +35 -33
- robosystems_client/models/invoice_line_item.py +13 -11
- robosystems_client/models/invoices_response.py +4 -2
- robosystems_client/models/link_token_request.py +21 -23
- robosystems_client/models/link_token_request_options_type_0.py +2 -0
- robosystems_client/models/list_org_graphs_response_200_item.py +2 -0
- robosystems_client/models/list_subgraphs_response.py +15 -13
- robosystems_client/models/list_table_files_response.py +27 -11
- robosystems_client/models/login_request.py +2 -0
- robosystems_client/models/logout_user_response_logoutuser.py +2 -0
- robosystems_client/models/{bulk_ingest_request.py → materialize_request.py} +25 -15
- robosystems_client/models/materialize_response.py +131 -0
- robosystems_client/models/materialize_status_response.py +172 -0
- robosystems_client/models/mcp_tool_call.py +7 -5
- robosystems_client/models/mcp_tool_call_arguments.py +2 -0
- robosystems_client/models/mcp_tools_response.py +4 -2
- robosystems_client/models/mcp_tools_response_tools_item.py +2 -0
- robosystems_client/models/o_auth_callback_request.py +18 -16
- robosystems_client/models/o_auth_init_request.py +14 -12
- robosystems_client/models/o_auth_init_request_additional_params_type_0.py +2 -0
- robosystems_client/models/o_auth_init_response.py +2 -0
- robosystems_client/models/offering_repository_plan.py +9 -7
- robosystems_client/models/offering_repository_plan_rate_limits_type_0.py +8 -8
- robosystems_client/models/operation_costs.py +4 -2
- robosystems_client/models/operation_costs_ai_operations.py +2 -0
- robosystems_client/models/operation_costs_token_pricing.py +5 -3
- robosystems_client/models/org_detail_response.py +13 -11
- robosystems_client/models/org_detail_response_graphs_item.py +2 -0
- robosystems_client/models/org_detail_response_limits_type_0.py +2 -0
- robosystems_client/models/org_detail_response_members_item.py +2 -0
- robosystems_client/models/org_limits_response.py +3 -1
- robosystems_client/models/org_limits_response_current_usage.py +2 -0
- robosystems_client/models/org_list_response.py +4 -2
- robosystems_client/models/org_member_list_response.py +4 -2
- robosystems_client/models/org_member_response.py +2 -0
- robosystems_client/models/org_response.py +2 -0
- robosystems_client/models/org_usage_response.py +7 -5
- robosystems_client/models/org_usage_response_daily_trend_item.py +2 -0
- robosystems_client/models/org_usage_response_graph_details_item.py +2 -0
- robosystems_client/models/org_usage_summary.py +18 -16
- robosystems_client/models/password_check_request.py +8 -6
- robosystems_client/models/password_check_response.py +3 -1
- robosystems_client/models/password_check_response_character_types.py +2 -0
- robosystems_client/models/password_policy_response.py +3 -1
- robosystems_client/models/password_policy_response_policy.py +2 -0
- robosystems_client/models/payment_method.py +23 -21
- robosystems_client/models/performance_insights.py +5 -3
- robosystems_client/models/performance_insights_operation_stats.py +2 -0
- robosystems_client/models/performance_insights_slow_queries_item.py +2 -0
- robosystems_client/models/plaid_connection_config.py +30 -30
- robosystems_client/models/plaid_connection_config_accounts_type_0_item.py +2 -0
- robosystems_client/models/plaid_connection_config_institution_type_0.py +2 -0
- robosystems_client/models/portal_session_response.py +2 -0
- robosystems_client/models/query_limits.py +2 -0
- robosystems_client/models/quick_books_connection_config.py +13 -11
- robosystems_client/models/rate_limits.py +2 -0
- robosystems_client/models/register_request.py +8 -6
- robosystems_client/models/repository_info.py +4 -2
- robosystems_client/models/repository_subscriptions.py +4 -2
- robosystems_client/models/resend_verification_email_response_resendverificationemail.py +2 -0
- robosystems_client/models/reset_password_request.py +2 -0
- robosystems_client/models/reset_password_validate_response.py +8 -6
- robosystems_client/models/save_view_request.py +138 -0
- robosystems_client/models/save_view_response.py +181 -0
- robosystems_client/models/schema_export_response.py +16 -14
- robosystems_client/models/schema_export_response_data_stats_type_0.py +2 -0
- robosystems_client/models/schema_export_response_schema_definition_type_0.py +2 -0
- robosystems_client/models/schema_info_response.py +3 -1
- robosystems_client/models/schema_info_response_schema.py +2 -0
- robosystems_client/models/schema_validation_request.py +18 -17
- robosystems_client/models/schema_validation_request_schema_definition_type_0.py +2 -0
- robosystems_client/models/schema_validation_response.py +28 -33
- robosystems_client/models/schema_validation_response_compatibility_type_0.py +2 -0
- robosystems_client/models/schema_validation_response_stats_type_0.py +2 -0
- robosystems_client/models/sec_connection_config.py +8 -6
- robosystems_client/models/selection_criteria.py +19 -17
- robosystems_client/models/service_offering_summary.py +2 -0
- robosystems_client/models/service_offerings_response.py +6 -4
- robosystems_client/models/sso_complete_request.py +2 -0
- robosystems_client/models/sso_exchange_request.py +8 -6
- robosystems_client/models/sso_exchange_response.py +2 -0
- robosystems_client/models/sso_token_response.py +2 -0
- robosystems_client/models/storage_info.py +4 -2
- robosystems_client/models/storage_info_included_per_tier.py +2 -0
- robosystems_client/models/storage_info_overage_pricing.py +2 -0
- robosystems_client/models/storage_limit_response.py +9 -7
- robosystems_client/models/storage_limits.py +8 -6
- robosystems_client/models/storage_summary.py +2 -0
- robosystems_client/models/structure_detail.py +85 -0
- robosystems_client/models/subgraph_quota_response.py +23 -21
- robosystems_client/models/subgraph_response.py +35 -35
- robosystems_client/models/subgraph_response_metadata_type_0.py +2 -0
- robosystems_client/models/subgraph_summary.py +14 -12
- robosystems_client/models/success_response.py +11 -9
- robosystems_client/models/success_response_data_type_0.py +2 -0
- robosystems_client/models/sync_connection_request.py +11 -9
- robosystems_client/models/sync_connection_request_sync_options_type_0.py +2 -0
- robosystems_client/models/sync_connection_response_syncconnection.py +2 -0
- robosystems_client/models/table_info.py +12 -10
- robosystems_client/models/table_list_response.py +4 -2
- robosystems_client/models/table_query_request.py +9 -7
- robosystems_client/models/table_query_response.py +2 -0
- robosystems_client/models/token_pricing.py +2 -0
- robosystems_client/models/transaction_summary_response.py +13 -11
- robosystems_client/models/upcoming_invoice.py +10 -8
- robosystems_client/models/update_api_key_request.py +13 -11
- robosystems_client/models/{update_file_status_response_updatefilestatus.py → update_file_response_updatefile.py} +7 -5
- robosystems_client/models/update_member_role_request.py +2 -0
- robosystems_client/models/update_org_request.py +14 -12
- robosystems_client/models/update_password_request.py +2 -0
- robosystems_client/models/update_user_request.py +13 -11
- robosystems_client/models/upgrade_subscription_request.py +2 -0
- robosystems_client/models/user_graphs_response.py +10 -8
- robosystems_client/models/user_response.py +22 -18
- robosystems_client/models/validation_error.py +8 -6
- robosystems_client/models/view_axis_config.py +276 -0
- robosystems_client/models/view_axis_config_element_labels_type_0.py +46 -0
- robosystems_client/models/view_axis_config_member_labels_type_0.py +46 -0
- robosystems_client/models/view_config.py +127 -0
- robosystems_client/models/view_source.py +144 -0
- robosystems_client/models/view_source_type.py +9 -0
- robosystems_client/types.py +9 -9
- {robosystems_client-0.2.15.dist-info → robosystems_client-0.2.16.dist-info}/METADATA +1 -1
- robosystems_client-0.2.16.dist-info/RECORD +418 -0
- robosystems_client/api/tables/delete_file.py +0 -317
- robosystems_client/api/tables/get_file_info.py +0 -249
- robosystems_client/api/tables/get_upload_url.py +0 -380
- robosystems_client/api/tables/ingest_tables.py +0 -456
- robosystems_client/api/tables/list_table_files.py +0 -329
- robosystems_client/api/tables/update_file_status.py +0 -395
- robosystems_client/models/bulk_ingest_response.py +0 -137
- robosystems_client/models/table_ingest_result.py +0 -107
- robosystems_client-0.2.15.dist-info/RECORD +0 -396
- {robosystems_client-0.2.15.dist-info → robosystems_client-0.2.16.dist-info}/WHEEL +0 -0
- {robosystems_client-0.2.15.dist-info → robosystems_client-0.2.16.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,617 @@
|
|
|
1
|
+
"""View Builder Client Extension
|
|
2
|
+
|
|
3
|
+
Client for building financial views and reports following the Financial Report Creator architecture.
|
|
4
|
+
Queries data from main graph, applies mappings, and generates views.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import List, Optional, Dict, Any
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from enum import Enum
|
|
10
|
+
import pandas as pd
|
|
11
|
+
from datetime import datetime
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ViewSourceType(Enum):
|
|
15
|
+
"""Source type for view generation"""
|
|
16
|
+
|
|
17
|
+
TRANSACTIONS = "transactions" # Generate from transaction aggregation
|
|
18
|
+
FACT_SET = "fact_set" # Pivot existing facts
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class ViewSource:
|
|
23
|
+
"""Source configuration for view generation"""
|
|
24
|
+
|
|
25
|
+
type: ViewSourceType
|
|
26
|
+
period_start: Optional[str] = None
|
|
27
|
+
period_end: Optional[str] = None
|
|
28
|
+
entity_id: Optional[str] = None
|
|
29
|
+
fact_set_id: Optional[str] = None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class ViewAxis:
|
|
34
|
+
"""Axis configuration for pivot table"""
|
|
35
|
+
|
|
36
|
+
type: str # "element", "period", "dimension"
|
|
37
|
+
dimension_axis: Optional[str] = None
|
|
38
|
+
hierarchy_root: Optional[str] = None
|
|
39
|
+
include_subtotals: bool = False
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class ViewConfig:
|
|
44
|
+
"""Configuration for view presentation"""
|
|
45
|
+
|
|
46
|
+
rows: List[ViewAxis]
|
|
47
|
+
columns: List[ViewAxis]
|
|
48
|
+
measures: Optional[List[str]] = None # Fact value columns to include
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass
|
|
52
|
+
class ViewResponse:
|
|
53
|
+
"""Response from view generation"""
|
|
54
|
+
|
|
55
|
+
facts: pd.DataFrame
|
|
56
|
+
metadata: Dict[str, Any]
|
|
57
|
+
execution_time_ms: int
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class ViewBuilderClient:
|
|
61
|
+
"""
|
|
62
|
+
Client for building financial views and reports.
|
|
63
|
+
|
|
64
|
+
Provides functionality to:
|
|
65
|
+
- Query trial balance from transactions
|
|
66
|
+
- Query existing facts with aspects
|
|
67
|
+
- Apply element mappings for aggregation
|
|
68
|
+
- Generate pivot table presentations
|
|
69
|
+
- Write views to subgraph workspaces
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
def __init__(self, query_client, element_mapping_client=None):
|
|
73
|
+
"""
|
|
74
|
+
Initialize with query client and optional element mapping client.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
query_client: RoboSystems query client
|
|
78
|
+
element_mapping_client: Optional ElementMappingClient for applying mappings
|
|
79
|
+
"""
|
|
80
|
+
self.query = query_client
|
|
81
|
+
self.element_mapping = element_mapping_client
|
|
82
|
+
|
|
83
|
+
async def aggregate_trial_balance(
|
|
84
|
+
self,
|
|
85
|
+
graph_id: str,
|
|
86
|
+
period_start: str,
|
|
87
|
+
period_end: str,
|
|
88
|
+
entity_id: Optional[str] = None,
|
|
89
|
+
requested_dimensions: Optional[List[str]] = None,
|
|
90
|
+
) -> pd.DataFrame:
|
|
91
|
+
"""
|
|
92
|
+
Aggregate transactions to trial balance (Mode 1: Transaction Aggregation).
|
|
93
|
+
|
|
94
|
+
This queries transaction data from the main graph and aggregates it
|
|
95
|
+
to create a trial balance with debit/credit totals and net balances.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
graph_id: Graph ID to query (main graph)
|
|
99
|
+
period_start: Start date (YYYY-MM-DD)
|
|
100
|
+
period_end: End date (YYYY-MM-DD)
|
|
101
|
+
entity_id: Optional entity filter
|
|
102
|
+
requested_dimensions: Optional dimension axes
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
DataFrame with trial balance data
|
|
106
|
+
"""
|
|
107
|
+
# Build WHERE clause
|
|
108
|
+
conditions = ["t.date >= $period_start", "t.date <= $period_end"]
|
|
109
|
+
params = {"period_start": period_start, "period_end": period_end}
|
|
110
|
+
|
|
111
|
+
if entity_id:
|
|
112
|
+
conditions.append("e.identifier = $entity_id")
|
|
113
|
+
params["entity_id"] = entity_id
|
|
114
|
+
|
|
115
|
+
where_clause = " AND ".join(conditions)
|
|
116
|
+
|
|
117
|
+
# Query transaction data with aggregation
|
|
118
|
+
cypher = f"""
|
|
119
|
+
MATCH (e:Entity)-[:ENTITY_HAS_TRANSACTION]->(t:Transaction)
|
|
120
|
+
-[:TRANSACTION_HAS_LINE_ITEM]->(li:LineItem)
|
|
121
|
+
-[:LINE_ITEM_RELATES_TO_ELEMENT]->(elem:Element)
|
|
122
|
+
WHERE {where_clause}
|
|
123
|
+
|
|
124
|
+
WITH elem,
|
|
125
|
+
sum(li.debit_amount) AS total_debits,
|
|
126
|
+
sum(li.credit_amount) AS total_credits
|
|
127
|
+
|
|
128
|
+
RETURN elem.identifier AS element_id,
|
|
129
|
+
elem.uri AS element_uri,
|
|
130
|
+
elem.name AS element_name,
|
|
131
|
+
elem.classification AS element_classification,
|
|
132
|
+
elem.balance AS element_balance,
|
|
133
|
+
elem.period_type AS element_period_type,
|
|
134
|
+
total_debits,
|
|
135
|
+
total_credits,
|
|
136
|
+
total_debits - total_credits AS net_balance
|
|
137
|
+
ORDER BY elem.name
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
result = await self.query.query(graph_id, cypher, params)
|
|
141
|
+
|
|
142
|
+
if not result or not result.data:
|
|
143
|
+
# Return empty DataFrame with expected columns
|
|
144
|
+
return pd.DataFrame(
|
|
145
|
+
columns=[
|
|
146
|
+
"element_id",
|
|
147
|
+
"element_uri",
|
|
148
|
+
"element_name",
|
|
149
|
+
"element_classification",
|
|
150
|
+
"element_balance",
|
|
151
|
+
"element_period_type",
|
|
152
|
+
"total_debits",
|
|
153
|
+
"total_credits",
|
|
154
|
+
"net_balance",
|
|
155
|
+
]
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
return pd.DataFrame(result.data)
|
|
159
|
+
|
|
160
|
+
async def query_facts_with_aspects(
|
|
161
|
+
self,
|
|
162
|
+
graph_id: str,
|
|
163
|
+
fact_set_id: Optional[str] = None,
|
|
164
|
+
period_start: Optional[str] = None,
|
|
165
|
+
period_end: Optional[str] = None,
|
|
166
|
+
entity_id: Optional[str] = None,
|
|
167
|
+
requested_dimensions: Optional[List[str]] = None,
|
|
168
|
+
) -> pd.DataFrame:
|
|
169
|
+
"""
|
|
170
|
+
Query existing facts with all aspects (Mode 2: Existing Facts).
|
|
171
|
+
|
|
172
|
+
This queries pre-computed facts from the main graph with their
|
|
173
|
+
elements, periods, units, and dimensions.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
graph_id: Graph ID to query (main graph)
|
|
177
|
+
fact_set_id: Optional fact set filter
|
|
178
|
+
period_start: Optional start date filter
|
|
179
|
+
period_end: Optional end date filter
|
|
180
|
+
entity_id: Optional entity filter
|
|
181
|
+
requested_dimensions: Optional dimension axes to include
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
DataFrame with fact data and aspects
|
|
185
|
+
"""
|
|
186
|
+
# Build WHERE clause
|
|
187
|
+
conditions = []
|
|
188
|
+
params = {}
|
|
189
|
+
|
|
190
|
+
if fact_set_id:
|
|
191
|
+
conditions.append("fs.identifier = $fact_set_id")
|
|
192
|
+
params["fact_set_id"] = fact_set_id
|
|
193
|
+
|
|
194
|
+
if period_start and period_end:
|
|
195
|
+
conditions.append("p.end_date >= $period_start")
|
|
196
|
+
conditions.append("p.end_date <= $period_end")
|
|
197
|
+
params["period_start"] = period_start
|
|
198
|
+
params["period_end"] = period_end
|
|
199
|
+
|
|
200
|
+
if entity_id:
|
|
201
|
+
conditions.append("e.identifier = $entity_id")
|
|
202
|
+
params["entity_id"] = entity_id
|
|
203
|
+
|
|
204
|
+
where_clause = f"WHERE {' AND '.join(conditions)}" if conditions else ""
|
|
205
|
+
|
|
206
|
+
# Query facts with all relationships
|
|
207
|
+
cypher = f"""
|
|
208
|
+
MATCH (fs:FactSet)-[:FACT_SET_CONTAINS_FACT]->(f:Fact)
|
|
209
|
+
MATCH (f)-[:FACT_HAS_ELEMENT]->(elem:Element)
|
|
210
|
+
MATCH (f)-[:FACT_HAS_PERIOD]->(p:Period)
|
|
211
|
+
OPTIONAL MATCH (f)-[:FACT_HAS_ENTITY]->(e:Entity)
|
|
212
|
+
OPTIONAL MATCH (f)-[:FACT_HAS_UNIT]->(u:Unit)
|
|
213
|
+
OPTIONAL MATCH (f)-[:FACT_HAS_DIMENSION]->(d:FactDimension)
|
|
214
|
+
{where_clause}
|
|
215
|
+
RETURN f.identifier AS fact_id,
|
|
216
|
+
f.numeric_value AS numeric_value,
|
|
217
|
+
f.value AS text_value,
|
|
218
|
+
elem.identifier AS element_id,
|
|
219
|
+
elem.uri AS element_uri,
|
|
220
|
+
elem.name AS element_name,
|
|
221
|
+
p.identifier AS period_id,
|
|
222
|
+
p.start_date AS period_start,
|
|
223
|
+
p.end_date AS period_end,
|
|
224
|
+
p.period_type AS period_type,
|
|
225
|
+
e.identifier AS entity_id,
|
|
226
|
+
e.name AS entity_name,
|
|
227
|
+
u.identifier AS unit_id,
|
|
228
|
+
u.name AS unit_name,
|
|
229
|
+
collect(DISTINCT {
|
|
230
|
+
"axis": d.axis_uri,
|
|
231
|
+
"member": d.member_uri
|
|
232
|
+
}) AS dimensions
|
|
233
|
+
"""
|
|
234
|
+
|
|
235
|
+
result = await self.query.query(graph_id, cypher, params)
|
|
236
|
+
|
|
237
|
+
if not result or not result.data:
|
|
238
|
+
return pd.DataFrame()
|
|
239
|
+
|
|
240
|
+
# Convert to DataFrame and expand dimensions if needed
|
|
241
|
+
df = pd.DataFrame(result.data)
|
|
242
|
+
|
|
243
|
+
# If requested_dimensions specified, filter/expand dimension columns
|
|
244
|
+
if requested_dimensions and not df.empty:
|
|
245
|
+
# This would expand dimension data into separate columns
|
|
246
|
+
# For now, keeping as nested structure
|
|
247
|
+
pass
|
|
248
|
+
|
|
249
|
+
return df
|
|
250
|
+
|
|
251
|
+
async def create_view(
|
|
252
|
+
self,
|
|
253
|
+
graph_id: str,
|
|
254
|
+
source: ViewSource,
|
|
255
|
+
view_config: Optional[ViewConfig] = None,
|
|
256
|
+
mapping_structure_id: Optional[str] = None,
|
|
257
|
+
workspace_id: Optional[str] = None,
|
|
258
|
+
) -> ViewResponse:
|
|
259
|
+
"""
|
|
260
|
+
Create a financial view from source data.
|
|
261
|
+
|
|
262
|
+
This is the main entry point for view generation. It:
|
|
263
|
+
1. Queries source data (transactions or facts)
|
|
264
|
+
2. Applies element mappings if specified
|
|
265
|
+
3. Generates pivot table presentation if configured
|
|
266
|
+
4. Optionally writes to subgraph workspace
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
graph_id: Main graph ID to query data from
|
|
270
|
+
source: Source configuration (transactions or fact set)
|
|
271
|
+
view_config: Optional pivot table configuration
|
|
272
|
+
mapping_structure_id: Optional mapping to apply for aggregation
|
|
273
|
+
workspace_id: Optional subgraph to write results to
|
|
274
|
+
|
|
275
|
+
Returns:
|
|
276
|
+
ViewResponse with generated view data
|
|
277
|
+
"""
|
|
278
|
+
start_time = datetime.now()
|
|
279
|
+
|
|
280
|
+
# Step 1: Get source data
|
|
281
|
+
if source.type == ViewSourceType.TRANSACTIONS:
|
|
282
|
+
fact_data = await self.aggregate_trial_balance(
|
|
283
|
+
graph_id=graph_id,
|
|
284
|
+
period_start=source.period_start,
|
|
285
|
+
period_end=source.period_end,
|
|
286
|
+
entity_id=source.entity_id,
|
|
287
|
+
)
|
|
288
|
+
source_type = "trial_balance_aggregation"
|
|
289
|
+
|
|
290
|
+
elif source.type == ViewSourceType.FACT_SET:
|
|
291
|
+
fact_data = await self.query_facts_with_aspects(
|
|
292
|
+
graph_id=graph_id,
|
|
293
|
+
fact_set_id=source.fact_set_id,
|
|
294
|
+
period_start=source.period_start,
|
|
295
|
+
period_end=source.period_end,
|
|
296
|
+
entity_id=source.entity_id,
|
|
297
|
+
)
|
|
298
|
+
source_type = "fact_set_query"
|
|
299
|
+
|
|
300
|
+
else:
|
|
301
|
+
raise ValueError(f"Unsupported source type: {source.type}")
|
|
302
|
+
|
|
303
|
+
# Step 2: Apply element mapping if specified
|
|
304
|
+
if mapping_structure_id and self.element_mapping:
|
|
305
|
+
# Get mapping structure from subgraph
|
|
306
|
+
mapping = await self.element_mapping.get_mapping_structure(
|
|
307
|
+
workspace_id or graph_id, mapping_structure_id
|
|
308
|
+
)
|
|
309
|
+
if mapping:
|
|
310
|
+
fact_data = self.element_mapping.apply_element_mapping(fact_data, mapping)
|
|
311
|
+
|
|
312
|
+
# Step 3: Generate pivot table if configured
|
|
313
|
+
if view_config:
|
|
314
|
+
fact_data = self._generate_pivot_table(fact_data, view_config)
|
|
315
|
+
|
|
316
|
+
# Step 4: Write to workspace if specified
|
|
317
|
+
if workspace_id:
|
|
318
|
+
await self._write_to_workspace(workspace_id, fact_data, source_type)
|
|
319
|
+
|
|
320
|
+
execution_time = int((datetime.now() - start_time).total_seconds() * 1000)
|
|
321
|
+
|
|
322
|
+
return ViewResponse(
|
|
323
|
+
facts=fact_data,
|
|
324
|
+
metadata={
|
|
325
|
+
"source": source_type,
|
|
326
|
+
"fact_count": len(fact_data),
|
|
327
|
+
"period_start": source.period_start,
|
|
328
|
+
"period_end": source.period_end,
|
|
329
|
+
"has_mapping": mapping_structure_id is not None,
|
|
330
|
+
"has_pivot": view_config is not None,
|
|
331
|
+
},
|
|
332
|
+
execution_time_ms=execution_time,
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
def _generate_pivot_table(
|
|
336
|
+
self, fact_data: pd.DataFrame, view_config: ViewConfig
|
|
337
|
+
) -> pd.DataFrame:
|
|
338
|
+
"""
|
|
339
|
+
Generate pivot table from fact data.
|
|
340
|
+
|
|
341
|
+
Args:
|
|
342
|
+
fact_data: Source fact DataFrame
|
|
343
|
+
view_config: Pivot configuration
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
Pivoted DataFrame
|
|
347
|
+
"""
|
|
348
|
+
if fact_data.empty:
|
|
349
|
+
return fact_data
|
|
350
|
+
|
|
351
|
+
# Determine value column
|
|
352
|
+
value_col = (
|
|
353
|
+
"numeric_value" if "numeric_value" in fact_data.columns else "net_balance"
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
# Build index (rows) and columns lists
|
|
357
|
+
index_cols = []
|
|
358
|
+
for axis in view_config.rows:
|
|
359
|
+
if axis.type == "element":
|
|
360
|
+
index_cols.append("element_name")
|
|
361
|
+
elif axis.type == "period":
|
|
362
|
+
index_cols.append("period_end")
|
|
363
|
+
elif axis.type == "dimension" and axis.dimension_axis:
|
|
364
|
+
# This would map dimension to column name
|
|
365
|
+
index_cols.append(f"dim_{axis.dimension_axis}")
|
|
366
|
+
|
|
367
|
+
column_cols = []
|
|
368
|
+
for axis in view_config.columns:
|
|
369
|
+
if axis.type == "element":
|
|
370
|
+
column_cols.append("element_name")
|
|
371
|
+
elif axis.type == "period":
|
|
372
|
+
column_cols.append("period_end")
|
|
373
|
+
elif axis.type == "dimension" and axis.dimension_axis:
|
|
374
|
+
column_cols.append(f"dim_{axis.dimension_axis}")
|
|
375
|
+
|
|
376
|
+
# Apply pivot_table
|
|
377
|
+
if index_cols and column_cols:
|
|
378
|
+
pivoted = pd.pivot_table(
|
|
379
|
+
fact_data,
|
|
380
|
+
values=value_col,
|
|
381
|
+
index=index_cols,
|
|
382
|
+
columns=column_cols,
|
|
383
|
+
aggfunc="sum",
|
|
384
|
+
fill_value=0,
|
|
385
|
+
)
|
|
386
|
+
# Flatten multi-index if needed
|
|
387
|
+
if isinstance(pivoted.columns, pd.MultiIndex):
|
|
388
|
+
pivoted.columns = ["_".join(map(str, col)) for col in pivoted.columns]
|
|
389
|
+
pivoted = pivoted.reset_index()
|
|
390
|
+
|
|
391
|
+
elif index_cols:
|
|
392
|
+
# Group by index only
|
|
393
|
+
pivoted = fact_data.groupby(index_cols)[value_col].sum().reset_index()
|
|
394
|
+
|
|
395
|
+
else:
|
|
396
|
+
pivoted = fact_data
|
|
397
|
+
|
|
398
|
+
# Add subtotals if requested
|
|
399
|
+
for axis in view_config.rows:
|
|
400
|
+
if axis.include_subtotals and axis.type == "element":
|
|
401
|
+
pivoted = self._add_subtotals(pivoted, axis.hierarchy_root)
|
|
402
|
+
|
|
403
|
+
return pivoted
|
|
404
|
+
|
|
405
|
+
def _add_subtotals(
|
|
406
|
+
self, df: pd.DataFrame, hierarchy_root: str = None
|
|
407
|
+
) -> pd.DataFrame:
|
|
408
|
+
"""
|
|
409
|
+
Add subtotal rows to DataFrame.
|
|
410
|
+
|
|
411
|
+
This would implement hierarchical subtotal logic.
|
|
412
|
+
Simplified for illustration.
|
|
413
|
+
"""
|
|
414
|
+
# This would:
|
|
415
|
+
# 1. Query hierarchy from graph
|
|
416
|
+
# 2. Group elements by parent
|
|
417
|
+
# 3. Calculate subtotals
|
|
418
|
+
# 4. Insert subtotal rows
|
|
419
|
+
return df
|
|
420
|
+
|
|
421
|
+
async def _write_to_workspace(
|
|
422
|
+
self, workspace_id: str, fact_data: pd.DataFrame, source_type: str
|
|
423
|
+
):
|
|
424
|
+
"""
|
|
425
|
+
Write view data to subgraph workspace.
|
|
426
|
+
|
|
427
|
+
Args:
|
|
428
|
+
workspace_id: Subgraph workspace ID
|
|
429
|
+
fact_data: Fact DataFrame to write
|
|
430
|
+
source_type: Source type for metadata
|
|
431
|
+
"""
|
|
432
|
+
if fact_data.empty:
|
|
433
|
+
return
|
|
434
|
+
|
|
435
|
+
# Create View node in workspace
|
|
436
|
+
import uuid
|
|
437
|
+
|
|
438
|
+
view_id = str(uuid.uuid4())
|
|
439
|
+
|
|
440
|
+
cypher = f"""
|
|
441
|
+
CREATE (v:View {{
|
|
442
|
+
identifier: '{view_id}',
|
|
443
|
+
source_type: '{source_type}',
|
|
444
|
+
created_at: datetime(),
|
|
445
|
+
fact_count: {len(fact_data)}
|
|
446
|
+
}})
|
|
447
|
+
RETURN v.identifier as view_id
|
|
448
|
+
"""
|
|
449
|
+
|
|
450
|
+
await self.query.query(workspace_id, cypher)
|
|
451
|
+
|
|
452
|
+
# Write facts in batches
|
|
453
|
+
for batch_start in range(0, len(fact_data), 100):
|
|
454
|
+
batch_end = min(batch_start + 100, len(fact_data))
|
|
455
|
+
batch = fact_data.iloc[batch_start:batch_end]
|
|
456
|
+
|
|
457
|
+
# Build CREATE statements for batch
|
|
458
|
+
creates = []
|
|
459
|
+
for _, row in batch.iterrows():
|
|
460
|
+
fact_props = {
|
|
461
|
+
"identifier": str(uuid.uuid4()),
|
|
462
|
+
"element_id": row.get("element_id", ""),
|
|
463
|
+
"value": float(row.get("net_balance", 0)),
|
|
464
|
+
"period_end": row.get("period_end", ""),
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
# Convert to Cypher properties string
|
|
468
|
+
props_str = ", ".join(
|
|
469
|
+
[
|
|
470
|
+
f"{k}: '{v}'" if isinstance(v, str) else f"{k}: {v}"
|
|
471
|
+
for k, v in fact_props.items()
|
|
472
|
+
]
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
creates.append(f"CREATE (f:ViewFact {{{props_str}}})")
|
|
476
|
+
|
|
477
|
+
batch_cypher = "\n".join(creates)
|
|
478
|
+
await self.query.query(workspace_id, batch_cypher)
|
|
479
|
+
|
|
480
|
+
async def build_fact_grid(
|
|
481
|
+
self,
|
|
482
|
+
graph_id: str,
|
|
483
|
+
view_source: ViewSource,
|
|
484
|
+
view_config: ViewConfig,
|
|
485
|
+
workspace_id: Optional[str] = None,
|
|
486
|
+
) -> Dict[str, Any]:
|
|
487
|
+
"""
|
|
488
|
+
Build a Fact Grid data structure for flexible presentation.
|
|
489
|
+
|
|
490
|
+
This follows the hypercube model from the architecture document,
|
|
491
|
+
creating a multidimensional structure that can generate multiple
|
|
492
|
+
presentation formats.
|
|
493
|
+
|
|
494
|
+
Args:
|
|
495
|
+
graph_id: Main graph to query data from
|
|
496
|
+
view_source: Source configuration
|
|
497
|
+
view_config: View configuration
|
|
498
|
+
workspace_id: Optional workspace to write to
|
|
499
|
+
|
|
500
|
+
Returns:
|
|
501
|
+
Fact Grid structure with dimensions, measures, and hierarchies
|
|
502
|
+
"""
|
|
503
|
+
# Get base fact data
|
|
504
|
+
view_response = await self.create_view(
|
|
505
|
+
graph_id=graph_id,
|
|
506
|
+
source=view_source,
|
|
507
|
+
view_config=view_config,
|
|
508
|
+
workspace_id=workspace_id,
|
|
509
|
+
)
|
|
510
|
+
|
|
511
|
+
fact_data = view_response.facts
|
|
512
|
+
|
|
513
|
+
# Build Fact Grid structure
|
|
514
|
+
fact_grid = {
|
|
515
|
+
"dimensions": self._extract_dimensions(fact_data),
|
|
516
|
+
"measures": self._extract_measures(fact_data),
|
|
517
|
+
"hierarchies": await self._build_hierarchies(graph_id, fact_data),
|
|
518
|
+
"facts": fact_data.to_dict("records"),
|
|
519
|
+
"metadata": {
|
|
520
|
+
"fact_count": len(fact_data),
|
|
521
|
+
"source": view_source.type.value,
|
|
522
|
+
"created_at": datetime.now().isoformat(),
|
|
523
|
+
**view_response.metadata,
|
|
524
|
+
},
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
return fact_grid
|
|
528
|
+
|
|
529
|
+
def _extract_dimensions(self, fact_data: pd.DataFrame) -> List[Dict[str, Any]]:
|
|
530
|
+
"""Extract dimensions from fact data"""
|
|
531
|
+
dimensions = []
|
|
532
|
+
|
|
533
|
+
# Time dimension
|
|
534
|
+
if "period_end" in fact_data.columns:
|
|
535
|
+
dimensions.append(
|
|
536
|
+
{
|
|
537
|
+
"name": "Time",
|
|
538
|
+
"type": "temporal",
|
|
539
|
+
"values": fact_data["period_end"].unique().tolist(),
|
|
540
|
+
}
|
|
541
|
+
)
|
|
542
|
+
|
|
543
|
+
# Element dimension
|
|
544
|
+
if "element_name" in fact_data.columns:
|
|
545
|
+
dimensions.append(
|
|
546
|
+
{
|
|
547
|
+
"name": "Element",
|
|
548
|
+
"type": "hierarchical",
|
|
549
|
+
"values": fact_data["element_name"].unique().tolist(),
|
|
550
|
+
}
|
|
551
|
+
)
|
|
552
|
+
|
|
553
|
+
# Entity dimension
|
|
554
|
+
if "entity_name" in fact_data.columns:
|
|
555
|
+
dimensions.append(
|
|
556
|
+
{
|
|
557
|
+
"name": "Entity",
|
|
558
|
+
"type": "categorical",
|
|
559
|
+
"values": fact_data["entity_name"].unique().tolist(),
|
|
560
|
+
}
|
|
561
|
+
)
|
|
562
|
+
|
|
563
|
+
return dimensions
|
|
564
|
+
|
|
565
|
+
def _extract_measures(self, fact_data: pd.DataFrame) -> List[Dict[str, Any]]:
|
|
566
|
+
"""Extract measures from fact data"""
|
|
567
|
+
measures = []
|
|
568
|
+
|
|
569
|
+
# Numeric measures
|
|
570
|
+
for col in ["net_balance", "numeric_value", "total_debits", "total_credits"]:
|
|
571
|
+
if col in fact_data.columns:
|
|
572
|
+
measures.append(
|
|
573
|
+
{"name": col, "type": "numeric", "aggregation": "sum", "format": "currency"}
|
|
574
|
+
)
|
|
575
|
+
|
|
576
|
+
return measures
|
|
577
|
+
|
|
578
|
+
async def _build_hierarchies(
|
|
579
|
+
self, graph_id: str, fact_data: pd.DataFrame
|
|
580
|
+
) -> Dict[str, Any]:
|
|
581
|
+
"""Build element hierarchies from graph"""
|
|
582
|
+
if "element_id" not in fact_data.columns:
|
|
583
|
+
return {}
|
|
584
|
+
|
|
585
|
+
element_ids = fact_data["element_id"].unique().tolist()
|
|
586
|
+
|
|
587
|
+
# Query element hierarchy from graph
|
|
588
|
+
cypher = """
|
|
589
|
+
MATCH (e:Element)
|
|
590
|
+
WHERE e.identifier IN $element_ids
|
|
591
|
+
OPTIONAL MATCH (e)-[:ELEMENT_HAS_PARENT]->(parent:Element)
|
|
592
|
+
RETURN e.identifier as element_id,
|
|
593
|
+
e.name as element_name,
|
|
594
|
+
parent.identifier as parent_id,
|
|
595
|
+
parent.name as parent_name
|
|
596
|
+
"""
|
|
597
|
+
|
|
598
|
+
result = await self.query.query(graph_id, cypher, {"element_ids": element_ids})
|
|
599
|
+
|
|
600
|
+
if not result or not result.data:
|
|
601
|
+
return {}
|
|
602
|
+
|
|
603
|
+
# Build hierarchy tree
|
|
604
|
+
hierarchy = {}
|
|
605
|
+
for row in result.data:
|
|
606
|
+
element_id = row["element_id"]
|
|
607
|
+
parent_id = row.get("parent_id")
|
|
608
|
+
|
|
609
|
+
if parent_id:
|
|
610
|
+
if parent_id not in hierarchy:
|
|
611
|
+
hierarchy[parent_id] = {"name": row["parent_name"], "children": []}
|
|
612
|
+
hierarchy[parent_id]["children"].append(element_id)
|
|
613
|
+
|
|
614
|
+
if element_id not in hierarchy:
|
|
615
|
+
hierarchy[element_id] = {"name": row["element_name"], "children": []}
|
|
616
|
+
|
|
617
|
+
return hierarchy
|