From 263e84bab8e5359f0abe89e43fb12ee88ccacad7 Mon Sep 17 00:00:00 2001 From: "Marcelo G. Almiron" Date: Wed, 28 May 2025 13:38:33 +0200 Subject: [PATCH 1/5] feat(ai): Add ChatResult converter to exec def Introduce a ExecutionDefinition builder for created visualizations returned from chat interactions. jira: GDAI-238 risk: low --- gooddata-sdk/gooddata_sdk/compute/service.py | 34 +- .../compute/visualization_to_sdk_converter.py | 102 + .../build_exec_def_from_chat_result.yaml | 2240 +++++++++++++++++ .../tests/compute/test_compute_service.py | 21 + 4 files changed, 2396 insertions(+), 1 deletion(-) create mode 100644 gooddata-sdk/gooddata_sdk/compute/visualization_to_sdk_converter.py create mode 100644 gooddata-sdk/tests/compute/fixtures/build_exec_def_from_chat_result.yaml diff --git a/gooddata-sdk/gooddata_sdk/compute/service.py b/gooddata-sdk/gooddata_sdk/compute/service.py index 16bd47e33..5ada0a5c9 100644 --- a/gooddata-sdk/gooddata_sdk/compute/service.py +++ b/gooddata-sdk/gooddata_sdk/compute/service.py @@ -16,7 +16,13 @@ from gooddata_api_client.model.search_result import SearchResult from gooddata_sdk.client import GoodDataApiClient -from gooddata_sdk.compute.model.execution import Execution, ExecutionDefinition, ResultCacheMetadata +from gooddata_sdk.compute.model.execution import ( + Execution, + ExecutionDefinition, + ResultCacheMetadata, + TableDimension, +) +from gooddata_sdk.compute.visualization_to_sdk_converter import VisualizationToSdkConverter logger = logging.getLogger(__name__) @@ -83,6 +89,32 @@ def retrieve_result_cache_metadata(self, workspace_id: str, result_id: str) -> R ) return ResultCacheMetadata(result_cache_metadata=result_cache_metadata) + def build_exec_def_from_chat_result(self, chat_result: ChatResult) -> ExecutionDefinition: + """ + Build execution definition from chat result. + + Args: + chat_result: ChatResult object containing visualization details from AI chat response + + Returns: + ExecutionDefinition: Execution definition built from chat result visualization + """ + vis_object = chat_result.created_visualizations["objects"][0] + metrics_def = vis_object.get("metrics") or [] + filters_def = vis_object.get("filters") or [] + dimensionality_def = vis_object.get("dimensionality") or [] + + metrics = [VisualizationToSdkConverter.convert_metric(m) for m in metrics_def] + filters = [VisualizationToSdkConverter.convert_filter(f) for f in filters_def] + attributes = [VisualizationToSdkConverter.convert_attribute(d) for d in dimensionality_def] + dimensions = [ + TableDimension(item_ids=[a.local_id for a in attributes]), + TableDimension(item_ids=["measureGroup"]), + ] + + exec_def = ExecutionDefinition(dimensions=dimensions, metrics=metrics, filters=filters, attributes=attributes) + return exec_def + def ai_chat(self, workspace_id: str, question: str) -> ChatResult: """ Chat with AI in GoodData workspace. diff --git a/gooddata-sdk/gooddata_sdk/compute/visualization_to_sdk_converter.py b/gooddata-sdk/gooddata_sdk/compute/visualization_to_sdk_converter.py new file mode 100644 index 000000000..70d88afd2 --- /dev/null +++ b/gooddata-sdk/gooddata_sdk/compute/visualization_to_sdk_converter.py @@ -0,0 +1,102 @@ +# (C) 2025 GoodData Corporation +from typing import Any + +from gooddata_sdk.compute.model.attribute import Attribute +from gooddata_sdk.compute.model.base import ObjId +from gooddata_sdk.compute.model.filter import ( + AbsoluteDateFilter, + AllTimeFilter, + Filter, + NegativeAttributeFilter, + PositiveAttributeFilter, + RelativeDateFilter, +) +from gooddata_sdk.compute.model.metric import Metric, SimpleMetric + + +class VisualizationToSdkConverter: + """ + Provides functions to convert visualization objects (dicts) to the SDK Compute model. + The input should be a visualization object as returned by `ai_chat`. + """ + + @staticmethod + def convert_attribute(attr_dict: dict[str, Any]) -> Attribute: + """ + Converts a visualization attribute dict to an SDK Attribute. + Expects keys: + - id: str - The identifier of the attribute + - title: str - The display title/label for the attribute + Returns: + Attribute: An SDK Attribute object with local_id and label set + """ + local_id = attr_dict["id"] + label = attr_dict["title"] + return Attribute(local_id=local_id, label=label) + + @staticmethod + def convert_filter(filter_dict: dict[str, Any]) -> Filter: + """ + Converts a visualization filter dict to an SDK Filter. + Expects keys: + - using: str - The identifier of the attribute/dataset to filter on + - include: list[str] (optional) - Values to include in positive filter + - exclude: list[str] (optional) - Values to exclude in negative filter + - from: str (optional) - Start date/shift for date filters + - to: str (optional) - End date/shift for date filters + - granularity: str (optional) - Time granularity for relative date filters + Returns: + Filter: One of: + - PositiveAttributeFilter: When include values specified + - NegativeAttributeFilter: When exclude values specified + - RelativeDateFilter: When granularity and from/to shifts specified + - AbsoluteDateFilter: When from/to dates specified + - AllTimeFilter: When no date range specified + """ + using = filter_dict["using"] + include = filter_dict.get("include") + exclude = filter_dict.get("exclude") + _from = filter_dict.get("from") + _to = filter_dict.get("to") + granularity = filter_dict.get("granularity") + + if include is not None: + return PositiveAttributeFilter(label=ObjId(using, "label"), values=include) + elif exclude is not None: + return NegativeAttributeFilter(label=ObjId(using, "label"), values=exclude) + elif granularity is not None and _from is not None and _to is not None: + return RelativeDateFilter( + dataset=ObjId(using, "dataset"), granularity=granularity, from_shift=_from, to_shift=_to + ) + elif _from is not None and _to is not None: + return AbsoluteDateFilter(dataset=ObjId(using, "dataset"), from_date=_from, to_date=_to) + else: + return AllTimeFilter(dataset=ObjId(using, "dataset")) + + @staticmethod + def convert_metric(metric_dict: dict[str, Any]) -> Metric: + """ + Converts a visualization metric dict to an SDK Metric. + Expects keys: + - id: str - The identifier of the metric/fact/attribute + - type: str - The type of object ("metric", "fact", or "attribute") + - aggFunction: str (optional) - Aggregation function for facts/attributes + Returns: + Metric: One of: + - SimpleMetric with no aggregation for metrics + - SimpleMetric with aggregation for facts + - SimpleMetric with "count" aggregation for attributes + """ + local_id = metric_dict["id"] + item = ObjId(metric_dict["id"], metric_dict["type"]) + + if metric_dict["type"] in ["metric", "fact"]: + aggregation = metric_dict.get("aggFunction") + return SimpleMetric(local_id=local_id, item=item, aggregation=aggregation) + + elif metric_dict["type"] == "attribute": + aggregation = "count" + return SimpleMetric(local_id=local_id, item=item, aggregation=aggregation) + + else: + raise ValueError(f"Unsupported metric type: {metric_dict['type']}") diff --git a/gooddata-sdk/tests/compute/fixtures/build_exec_def_from_chat_result.yaml b/gooddata-sdk/tests/compute/fixtures/build_exec_def_from_chat_result.yaml new file mode 100644 index 000000000..b41154bd4 --- /dev/null +++ b/gooddata-sdk/tests/compute/fixtures/build_exec_def_from_chat_result.yaml @@ -0,0 +1,2240 @@ +# (C) 2025 GoodData Corporation +version: 1 +interactions: + - request: + method: GET + uri: http://localhost:3000/api/v1/entities/workspaces/demo_testing?include=workspaces + body: null + headers: + Accept: + - application/vnd.gooddata.api+json + Accept-Encoding: + - br, gzip, deflate + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 404 + message: Not Found + headers: + Cache-Control: + - max-age=5, private + Content-Length: + - '172' + Content-Type: + - application/problem+json + DATE: &id001 + - PLACEHOLDER + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + detail: The requested endpoint does not exist or you do not have permission + to access it. + status: 404 + title: Not Found + traceId: 85c696d39f778b59e3021bc8655c417c + - request: + method: GET + uri: http://localhost:3000/api/v1/entities/workspaces/demo_testing?include=workspaces + body: null + headers: + Accept: + - application/vnd.gooddata.api+json + Accept-Encoding: + - br, gzip, deflate + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 404 + message: Not Found + headers: + Cache-Control: + - max-age=5, private + Content-Length: + - '172' + Content-Type: + - application/problem+json + DATE: *id001 + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + detail: The requested endpoint does not exist or you do not have permission + to access it. + status: 404 + title: Not Found + traceId: 03937b37e651ec6d97d5d94df689ba7e + - request: + method: POST + uri: http://localhost:3000/api/v1/entities/workspaces + body: + data: + id: demo_testing + type: workspace + attributes: + name: demo_testing + headers: + Accept: + - application/vnd.gooddata.api+json + Accept-Encoding: + - br, gzip, deflate + Content-Type: + - application/vnd.gooddata.api+json + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 201 + message: Created + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Content-Length: + - '167' + Content-Type: + - application/vnd.gooddata.api+json + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + data: + id: demo_testing + type: workspace + attributes: + name: demo_testing + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo_testing + - request: + method: PUT + uri: http://localhost:3000/api/v1/layout/workspaces/demo_testing/logicalModel + body: + ldm: + datasets: + - grain: + - id: campaign_channel_id + type: attribute + id: campaign_channels + references: + - identifier: + id: campaigns + type: dataset + multivalue: false + sources: + - column: campaign_id + target: + id: campaign_id + type: attribute + dataType: INT + title: Campaign channels + description: Campaign channels + attributes: + - id: campaign_channel_id + labels: [] + sourceColumn: campaign_channel_id + title: Campaign channel id + sourceColumnDataType: STRING + description: Campaign channel id + tags: + - Campaign channels + - id: campaign_channels.category + labels: [] + sourceColumn: category + title: Category + sourceColumnDataType: STRING + description: Category + tags: + - Campaign channels + - id: type + labels: [] + sourceColumn: type + title: Type + sourceColumnDataType: STRING + description: Type + tags: + - Campaign channels + facts: + - id: budget + sourceColumn: budget + title: Budget + sourceColumnDataType: NUMERIC + description: Budget + tags: + - Campaign channels + - id: spend + sourceColumn: spend + title: Spend + sourceColumnDataType: NUMERIC + description: Spend + tags: + - Campaign channels + dataSourceTableId: + dataSourceId: pg_local_docker-demo + id: campaign_channels + type: dataSource + path: + - demo_6d9051d9069a8468 + - campaign_channels + tags: + - Campaign channels + - grain: + - id: campaign_id + type: attribute + id: campaigns + references: [] + title: Campaigns + description: Campaigns + attributes: + - id: campaign_id + labels: [] + sourceColumn: campaign_id + title: Campaign id + sourceColumnDataType: INT + description: Campaign id + tags: + - Campaigns + - id: campaign_name + labels: [] + sourceColumn: campaign_name + title: Campaign name + sourceColumnDataType: STRING + description: Campaign name + tags: + - Campaigns + facts: [] + dataSourceTableId: + dataSourceId: pg_local_docker-demo + id: campaigns + type: dataSource + path: + - demo_6d9051d9069a8468 + - campaigns + tags: + - Campaigns + - grain: + - id: customer_id + type: attribute + id: customers + references: [] + title: Customers + description: Customers + attributes: + - id: customer_id + labels: [] + sourceColumn: customer_id + title: Customer id + sourceColumnDataType: INT + description: Customer id + tags: + - Customers + - id: customer_name + labels: [] + sourceColumn: customer_name + title: Customer name + sourceColumnDataType: STRING + description: Customer name + tags: + - Customers + - id: region + labels: [] + sourceColumn: region + title: Region + sourceColumnDataType: STRING + description: Region + tags: + - Customers + - id: state + labels: + - id: geo__state__location + sourceColumn: geo__state__location + title: Location + sourceColumnDataType: STRING + description: Location + tags: + - Customers + sourceColumn: state + title: State + sourceColumnDataType: STRING + description: State + tags: + - Customers + facts: [] + dataSourceTableId: + dataSourceId: pg_local_docker-demo + id: customers + type: dataSource + path: + - demo_6d9051d9069a8468 + - customers + tags: + - Customers + - grain: + - id: order_line_id + type: attribute + id: order_lines + references: + - identifier: + id: campaigns + type: dataset + multivalue: false + sources: + - column: campaign_id + target: + id: campaign_id + type: attribute + dataType: INT + - identifier: + id: customers + type: dataset + multivalue: false + sources: + - column: customer_id + target: + id: customer_id + type: attribute + dataType: INT + - identifier: + id: date + type: dataset + multivalue: false + sources: + - column: date + target: + id: date + type: date + dataType: DATE + - identifier: + id: products + type: dataset + multivalue: false + sources: + - column: product_id + target: + id: product_id + type: attribute + dataType: INT + title: Order lines + description: Order lines + attributes: + - id: order_id + labels: [] + sourceColumn: order_id + title: Order id + sourceColumnDataType: STRING + description: Order id + tags: + - Order lines + - id: order_line_id + labels: [] + sourceColumn: order_line_id + title: Order line id + sourceColumnDataType: STRING + description: Order line id + tags: + - Order lines + - id: order_status + labels: [] + sourceColumn: order_status + title: Order status + sourceColumnDataType: STRING + description: Order status + tags: + - Order lines + facts: + - id: price + sourceColumn: price + title: Price + sourceColumnDataType: NUMERIC + description: Price + tags: + - Order lines + - id: quantity + sourceColumn: quantity + title: Quantity + sourceColumnDataType: NUMERIC + description: Quantity + tags: + - Order lines + dataSourceTableId: + dataSourceId: pg_local_docker-demo + id: order_lines + type: dataSource + path: + - demo_6d9051d9069a8468 + - order_lines + tags: + - Order lines + workspaceDataFilterColumns: + - dataType: STRING + name: wdf__region + - dataType: STRING + name: wdf__state + - grain: + - id: product_id + type: attribute + id: products + references: [] + title: Products + description: Products + attributes: + - id: product_id + labels: [] + sourceColumn: product_id + title: Product id + sourceColumnDataType: INT + description: Product id + tags: + - Products + - id: product_name + labels: [] + sourceColumn: product_name + title: Product name + sourceColumnDataType: STRING + description: Product name + tags: + - Products + - id: products.category + labels: [] + sourceColumn: category + title: Category + sourceColumnDataType: STRING + description: Category + tags: + - Products + facts: [] + dataSourceTableId: + dataSourceId: pg_local_docker-demo + id: products + type: dataSource + path: + - demo_6d9051d9069a8468 + - products + tags: + - Products + dateInstances: + - granularities: + - DAY + - WEEK + - MONTH + - QUARTER + - YEAR + granularitiesFormatting: + titleBase: '' + titlePattern: '%titleBase - %granularityTitle' + id: date + title: Date + description: '' + tags: + - Date + headers: + Accept-Encoding: + - br, gzip, deflate + Content-Type: + - application/json + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 204 + message: No Content + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: '' + - request: + method: PUT + uri: http://localhost:3000/api/v1/layout/workspaces/demo_testing/analyticsModel + body: + analytics: + analyticalDashboards: + - content: + filterContextRef: + identifier: + id: 4717b786-2c2e-4596-adb5-4f8b0ab0e19a + type: filterContext + layout: + sections: + - header: + description: All in one description + title: All in one title + items: + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: top_10_customers + type: visualizationObject + localIdentifier: 2c7400ac-5f63-46f8-aa12-a2debe13fd14 + properties: {} + title: Top 10 Customers + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: revenue_by_product + type: visualizationObject + localIdentifier: a50daab7-fb78-45eb-a2b4-d5cc8cbd89e9 + properties: {} + title: Revenue by Product + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: revenue_by_category_trend + type: visualizationObject + localIdentifier: efccc783-5896-4eb6-890f-2e51ece3f159 + properties: {} + title: Revenue by Category Trend + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: product_saleability + type: visualizationObject + localIdentifier: d738d85f-e935-4e2c-b8b4-a8b456f55079 + properties: {} + title: Product Saleability + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: product_categories_pie_chart + type: visualizationObject + localIdentifier: 8c194c85-bad6-42da-b4e3-08d270278316 + properties: {} + title: Product Categories Pie Chart + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: percentage_of_customers_by_region + type: visualizationObject + localIdentifier: 2c3307b2-581f-4bab-9252-6b5279565b24 + properties: {} + title: Percentage of Customers by Region + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: customers_trend + type: visualizationObject + localIdentifier: 87505bb0-d954-4add-811d-f4e75e431660 + properties: {} + title: Customers Trend + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: campaign_spend + type: visualizationObject + localIdentifier: 0cb01f6a-6ea6-4c22-bb12-ded00a9eac66 + properties: {} + title: Campaign Spend + type: insight + - size: + xl: + gridWidth: 12 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: percent_revenue_per_product_by_customer_and_category + type: visualizationObject + localIdentifier: 2213d6e4-6df7-458e-806d-f02bae5ce66a + properties: {} + title: '% Revenue per Product by Customer and Category' + type: insight + type: IDashboardLayoutSection + type: IDashboardLayout + version: '2' + id: b2f2d436-9831-4fe0-81df-8c59fd33242b + title: All visualizations 1 with custom filter + description: '' + analyticalDashboardExtensions: [] + attributeHierarchies: [] + dashboardPlugins: [] + filterContexts: + - content: + filters: + - attributeFilter: + attributeElements: + uris: + - Biolid + - ChalkTalk + - Compglass + - Elentrix + displayForm: + identifier: + id: product_name + type: label + filterElementsBy: [] + localIdentifier: 6b94bbb585d44c79967867719e524fae + negativeSelection: false + selectionMode: multi + version: '2' + id: 4717b786-2c2e-4596-adb5-4f8b0ab0e19a + title: filterContext + description: '' + - content: + filters: + - dateFilter: + from: '0' + granularity: GDC.time.year + to: '0' + type: relative + version: '2' + id: 9f2b1f37-befa-450e-a6cc-dc576845c412 + title: filterContext + description: '' + metrics: + - content: + format: '#,##0' + maql: SELECT COUNT({attribute/customer_id},{attribute/order_line_id}) + id: amount_of_active_customers + title: '# of Active Customers' + description: '' + - content: + format: '#,##0' + maql: SELECT COUNT({attribute/order_id}) + id: amount_of_orders + title: '# of Orders' + description: '' + - content: + format: '#,##0' + maql: 'SELECT {metric/amount_of_active_customers} WHERE (SELECT {metric/revenue} + BY {attribute/customer_id}) > 10000 ' + id: amount_of_top_customers + title: '# of Top Customers' + description: '' + - content: + format: '#,##0.00' + maql: SELECT {metric/amount_of_orders} WHERE NOT ({label/order_status} + IN ("null", "Returned", "Canceled")) + id: amount_of_valid_orders + title: '# of Valid Orders' + description: '' + - content: + format: $#,##0 + maql: SELECT SUM({fact/spend}) + id: campaign_spend + title: Campaign Spend + description: '' + - content: + format: $#,##0 + maql: SELECT SUM({fact/price}*{fact/quantity}) + id: order_amount + title: Order Amount + description: '' + - content: + format: '#,##0.0%' + maql: SELECT {metric/revenue} / {metric/total_revenue} + id: percent_revenue + title: '% Revenue' + description: '' + - content: + format: '#,##0.0%' + maql: "SELECT\n (SELECT {metric/revenue} WHERE (SELECT {metric/revenue_top_10}\ + \ BY {attribute/customer_id}) > 0)\n /\n {metric/revenue}" + id: percent_revenue_from_top_10_customers + title: '% Revenue from Top 10 Customers' + description: '' + - content: + format: '#,##0.0%' + maql: "SELECT\n (SELECT {metric/revenue} WHERE (SELECT {metric/revenue_top_10_percent}\ + \ BY {attribute/customer_id}) > 0)\n /\n {metric/revenue}" + id: percent_revenue_from_top_10_percent_customers + title: '% Revenue from Top 10% Customers' + description: '' + - content: + format: '#,##0.0%' + maql: "SELECT\n (SELECT {metric/revenue} WHERE (SELECT {metric/revenue_top_10_percent}\ + \ BY {attribute/product_id}) > 0)\n /\n {metric/revenue}" + id: percent_revenue_from_top_10_percent_products + title: '% Revenue from Top 10% Products' + description: '' + - content: + format: '#,##0.0%' + maql: "SELECT\n (SELECT {metric/revenue} WHERE (SELECT {metric/revenue_top_10}\ + \ BY {attribute/product_id}) > 0)\n /\n {metric/revenue}" + id: percent_revenue_from_top_10_products + title: '% Revenue from Top 10 Products' + description: '' + - content: + format: '#,##0.0%' + maql: SELECT {metric/revenue} / (SELECT {metric/revenue} BY {attribute/products.category}, + ALL OTHER) + id: percent_revenue_in_category + title: '% Revenue in Category' + description: '' + - content: + format: '#,##0.0%' + maql: SELECT {metric/revenue} / (SELECT {metric/revenue} BY ALL {attribute/product_id}) + id: percent_revenue_per_product + title: '% Revenue per Product' + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/order_amount} WHERE NOT ({label/order_status} + IN ("null", "Returned", "Canceled")) + id: revenue + title: Revenue + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE {label/products.category} IN ("Clothing") + id: revenue-clothing + title: Revenue (Clothing) + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE {label/products.category} IN ( + "Electronics") + id: revenue-electronic + title: Revenue (Electronic) + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE {label/products.category} IN ("Home") + id: revenue-home + title: Revenue (Home) + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE {label/products.category} IN ("Outdoor") + id: revenue-outdoor + title: Revenue (Outdoor) + description: '' + - content: + format: $#,##0.0 + maql: SELECT AVG(SELECT {metric/revenue} BY {attribute/customer_id}) + id: revenue_per_customer + title: Revenue per Customer + description: '' + - content: + format: $#,##0.0 + maql: SELECT {metric/revenue} / {metric/campaign_spend} + id: revenue_per_dollar_spent + title: Revenue per Dollar Spent + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE TOP(10) OF ({metric/revenue}) + id: revenue_top_10 + title: Revenue / Top 10 + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE TOP(10%) OF ({metric/revenue}) + id: revenue_top_10_percent + title: Revenue / Top 10% + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/revenue} BY ALL OTHER + id: total_revenue + title: Total Revenue + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/total_revenue} WITHOUT PARENT FILTER + id: total_revenue-no_filters + title: Total Revenue (No Filters) + description: '' + visualizationObjects: + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: campaign_spend + type: metric + localIdentifier: d319bcb2d8c04442a684e3b3cd063381 + title: Campaign Spend + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: campaign_channels.category + type: label + localIdentifier: 291c085e7df8420db84117ca49f59c49 + localIdentifier: view + - items: + - attribute: + displayForm: + identifier: + id: campaign_name + type: label + localIdentifier: d9dd143d647d4d148405a60ec2cf59bc + localIdentifier: segment + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: type + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: campaign_channels.category + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: campaign_name + type: label + notIn: + values: [] + properties: + controls: + legend: + position: bottom + version: '2' + visualizationUrl: local:treemap + id: campaign_spend + title: Campaign Spend + description: '' + - content: + buckets: + - items: + - measure: + alias: Active Customers + definition: + measureDefinition: + computeRatio: false + filters: [] + item: + identifier: + id: amount_of_active_customers + type: metric + localIdentifier: 2ba0b87b59ca41a4b1530e81a5c1d081 + title: '# of Active Customers' + localIdentifier: measures + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue_per_customer + type: metric + localIdentifier: ec0606894b9f4897b7beaf1550608928 + title: Revenue per Customer + localIdentifier: secondary_measures + - items: + - attribute: + displayForm: + identifier: + id: date.month + type: label + localIdentifier: 0de7d7f08af7480aa636857a26be72b6 + localIdentifier: view + filters: + - relativeDateFilter: + dataSet: + identifier: + id: date + type: dataset + from: -11 + granularity: GDC.time.month + to: 0 + properties: + controls: + colorMapping: + - color: + type: guid + value: '20' + id: 2ba0b87b59ca41a4b1530e81a5c1d081 + - color: + type: guid + value: '4' + id: ec0606894b9f4897b7beaf1550608928 + dualAxis: true + legend: + position: bottom + primaryChartType: column + secondaryChartType: line + secondary_yaxis: + measures: + - ec0606894b9f4897b7beaf1550608928 + xaxis: + name: + visible: false + rotation: auto + version: '2' + visualizationUrl: local:combo2 + id: customers_trend + title: Customers Trend + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: percent_revenue_per_product + type: metric + localIdentifier: 08d8346c1ce7438994b251991c0fbf65 + title: '% Revenue per Product' + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: b2350c06688b4da9b3833ebcce65527f + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: customer_name + type: label + localIdentifier: 7a4045fd00ac44579f52406df679435f + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: 6a003ffd14994237ba64c4a02c488429 + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: 75ea396d0c8b48098e31dccf8b5801d3 + localIdentifier: attribute + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: customer_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + properties: + sortItems: + - attributeSortItem: + attributeIdentifier: 7a4045fd00ac44579f52406df679435f + direction: asc + version: '2' + visualizationUrl: local:table + id: percent_revenue_per_product_by_customer_and_category + title: '% Revenue per Product by Customer and Category' + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: amount_of_active_customers + type: metric + localIdentifier: 1a14cdc1293c46e89a2e25d3e741d235 + title: '# of Active Customers' + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: date.month + type: label + localIdentifier: c1feca1864244ec2ace7a9b9d7fda231 + localIdentifier: view + - items: + - attribute: + displayForm: + identifier: + id: region + type: label + localIdentifier: 530cddbd7ca04d039e73462d81ed44d5 + localIdentifier: stack + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: region + type: label + notIn: + values: [] + - relativeDateFilter: + dataSet: + identifier: + id: date + type: dataset + from: -11 + granularity: GDC.time.month + to: 0 + properties: + controls: + legend: + position: bottom + stackMeasuresToPercent: true + version: '2' + visualizationUrl: local:area + id: percentage_of_customers_by_region + title: Percentage of Customers by Region + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 590d332ef686468b8878ae41b23341c6 + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: b166c71091864312a14c7ae8ff886ffe + localIdentifier: view + - items: + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: e920a50e0bbb49788df0aac53634c1cd + localIdentifier: segment + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + properties: + controls: + legend: + position: bottom + version: '2' + visualizationUrl: local:treemap + id: product_breakdown + title: Product Breakdown + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + computeRatio: true + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 162b857af49d45769bc12604a5c192b9 + title: '% Revenue' + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: fe513cef1c6244a5ac21c5f49c56b108 + localIdentifier: view + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + properties: + controls: + dataLabels: + visible: auto + legend: + position: bottom + version: '2' + visualizationUrl: local:donut + id: product_categories_pie_chart + title: Product Categories Pie Chart + description: '' + - content: + buckets: + - items: + - measure: + alias: Previous Period + definition: + popMeasureDefinition: + measureIdentifier: c82e025fa2db4afea9a600a424591dbe + popAttribute: + identifier: + id: date.year + type: label + localIdentifier: c82e025fa2db4afea9a600a424591dbe_pop + - measure: + alias: This Period + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: c82e025fa2db4afea9a600a424591dbe + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: c804ef5ba7944a5a9f360c86a9e95e9a + localIdentifier: view + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + - relativeDateFilter: + dataSet: + identifier: + id: date + type: dataset + from: -11 + granularity: GDC.time.month + to: 0 + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + properties: + controls: + legend: + position: bottom + stackMeasures: false + xaxis: + name: + visible: false + yaxis: + name: + visible: false + version: '2' + visualizationUrl: local:column + id: product_revenue_comparison-over_previous_period + title: Product Revenue Comparison (over previous period) + description: '' + - content: + buckets: + - items: + - measure: + alias: Number of Orders + definition: + measureDefinition: + filters: [] + item: + identifier: + id: amount_of_orders + type: metric + localIdentifier: aeb5d51a162d4b59aba3bd6ddebcc780 + title: '# of Orders' + localIdentifier: measures + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 94b3edd3a73c4a48a4d13bbe9442cc98 + title: Revenue + localIdentifier: secondary_measures + - items: + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: d2a991bdd123448eb2be73d79f1180c4 + localIdentifier: attribute + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + properties: + controls: + dataLabels: + visible: auto + grid: + enabled: true + version: '2' + visualizationUrl: local:scatter + id: product_saleability + title: Product Saleability + description: '' + - content: + buckets: + - items: + - measure: + alias: Items Sold + definition: + measureDefinition: + aggregation: sum + filters: [] + item: + identifier: + id: quantity + type: fact + format: '#,##0.00' + localIdentifier: 29486504dd0e4a36a18b0b2f792d3a46 + title: Sum of Quantity + - measure: + definition: + measureDefinition: + aggregation: avg + filters: [] + item: + identifier: + id: price + type: fact + format: '#,##0.00' + localIdentifier: aa6391acccf1452f8011201aef9af492 + title: Avg Price + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: percent_revenue_in_category + type: metric + localIdentifier: 2cd39539d8da46c9883e63caa3ba7cc0 + title: '% Revenue in Category' + - measure: + alias: Total Revenue + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 9a0f08331c094c7facf2a0b4f418de0a + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: 06bc6b3b9949466494e4f594c11f1bff + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: 192668bfb6a74e9ab7b5d1ce7cb68ea3 + localIdentifier: attribute + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: customer_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + properties: + sortItems: + - attributeSortItem: + attributeIdentifier: 06bc6b3b9949466494e4f594c11f1bff + direction: asc + version: '2' + visualizationUrl: local:table + id: revenue_and_quantity_by_product_and_category + title: Revenue and Quantity by Product and Category + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 7df6c34387744d69b23ec92e1a5cf543 + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: date.month + type: label + localIdentifier: 4bb4fc1986c546de9ad976e6ec23fed4 + localIdentifier: trend + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: 34bddcb1cd024902a82396216b0fa9d8 + localIdentifier: segment + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + - relativeDateFilter: + dataSet: + identifier: + id: date + type: dataset + granularity: GDC.time.year + properties: + controls: + legend: + position: bottom + version: '2' + visualizationUrl: local:line + id: revenue_by_category_trend + title: Revenue by Category Trend + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 4ae3401bdbba4938afe983df4ba04e1c + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: 1c8ba72dbfc84ddd913bf81dc355c427 + localIdentifier: view + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + properties: {} + version: '2' + visualizationUrl: local:bar + id: revenue_by_product + title: Revenue by Product + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: campaign_spend + type: metric + localIdentifier: 13a50d811e474ac6808d8da7f4673b35 + title: Campaign Spend + localIdentifier: measures + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue_per_dollar_spent + type: metric + localIdentifier: a0f15e82e6334280a44dbedc7d086e7c + title: Revenue per Dollar Spent + localIdentifier: secondary_measures + - items: + - attribute: + displayForm: + identifier: + id: campaign_name + type: label + localIdentifier: 1d9fa968bafb423eb29c938dfb1207ff + localIdentifier: attribute + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: campaign_name + type: label + notIn: + values: [] + properties: + controls: + xaxis: + min: '0' + yaxis: + min: '0' + version: '2' + visualizationUrl: local:scatter + id: revenue_per_usd_vs_spend_by_campaign + title: Revenue per $ vs Spend by Campaign + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + computeRatio: false + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 60c854969a9c4c278ab596d99c222e92 + title: Revenue + localIdentifier: measures + - items: + - measure: + alias: Number of Orders + definition: + measureDefinition: + computeRatio: false + filters: [] + item: + identifier: + id: amount_of_orders + type: metric + localIdentifier: c2fa7ef48cc54af99f8c280eb451e051 + title: '# of Orders' + localIdentifier: secondary_measures + - items: + - attribute: + displayForm: + identifier: + id: date.month + type: label + localIdentifier: 413ac374b65648fa96826ca01d47bdda + localIdentifier: view + filters: + - relativeDateFilter: + dataSet: + identifier: + id: date + type: dataset + from: -3 + granularity: GDC.time.quarter + to: 0 + properties: + controls: + dualAxis: true + legend: + position: bottom + primaryChartType: column + secondaryChartType: line + secondary_yaxis: + measures: + - c2fa7ef48cc54af99f8c280eb451e051 + xaxis: + name: + visible: false + rotation: auto + version: '2' + visualizationUrl: local:combo2 + id: revenue_trend + title: Revenue Trend + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue_top_10 + type: metric + localIdentifier: 3f127ccfe57a40399e23f9ae2a4ad810 + title: Revenue / Top 10 + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: customer_name + type: label + localIdentifier: f4e39e24f11e4827a191c30d65c89d2c + localIdentifier: view + - items: + - attribute: + displayForm: + identifier: + id: state + type: label + localIdentifier: bbccd430176d428caed54c99afc9589e + localIdentifier: stack + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: customer_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: state + type: label + notIn: + values: [] + properties: + controls: + legend: + position: bottom + version: '2' + visualizationUrl: local:bar + id: top_10_customers + title: Top 10 Customers + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue_top_10 + type: metric + localIdentifier: 77dc71bbac92412bac5f94284a5919df + title: Revenue / Top 10 + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: 781952e728204dcf923142910cc22ae2 + localIdentifier: view + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: fe513cef1c6244a5ac21c5f49c56b108 + localIdentifier: stack + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + properties: + controls: + legend: + position: bottom + version: '2' + visualizationUrl: local:bar + id: top_10_products + title: Top 10 Products + description: '' + exportDefinitions: [] + headers: + Accept-Encoding: + - br, gzip, deflate + Content-Type: + - application/json + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 204 + message: No Content + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: '' + - request: + method: POST + uri: http://localhost:3000/api/v1/actions/workspaces/demo_testing/ai/chat + body: + question: What is the total revenue for the year 2024? + headers: + Accept: + - application/json + Accept-Encoding: + - br, gzip, deflate + Content-Type: + - application/json + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Content-Length: + - '856' + Content-Type: + - application/json + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + routing: + useCase: CREATE_VISUALIZATION + reasoning: Creating a new visualization ... + createdVisualizations: + objects: + - id: total_revenue_for_2024 + title: Total Revenue for 2024 + visualizationType: HEADLINE + metrics: + - id: total_revenue + type: metric + title: Total Revenue + dimensionality: [] + filters: + - using: date.year + include: + - '2024' + suggestions: + - query: Slice by 'Date - Month/Year' to see monthly revenue distribution + for 2024 + label: Slice by month/year + - query: Slice by 'Date - Quarter/Year' to see quarterly revenue + distribution for 2024 + label: Slice by quarter/year + reasoning: ' + + + + + + Here is a headline showing the Total Revenue for 2024. + + - Metrics: Total Revenue + + - Attributes: None + + - Filter: Include Date. Year: 2024 + + + ' + chatHistoryInteractionId: bc57ccb7ee8f4eec8eed2da588fdb9c3 + - request: + method: POST + uri: http://localhost:3000/api/v1/actions/workspaces/demo_testing/execution/afm/execute + body: + execution: + attributes: [] + filters: + - positiveAttributeFilter: + in: + values: + - '2024' + label: + identifier: + id: date.year + type: label + measures: + - definition: + measure: + item: + identifier: + id: total_revenue + type: metric + computeRatio: false + filters: [] + localIdentifier: total_revenue + resultSpec: + dimensions: + - itemIdentifiers: [] + localIdentifier: dim_0 + - itemIdentifiers: + - measureGroup + localIdentifier: dim_1 + headers: + Accept: + - application/json + Accept-Encoding: + - br, gzip, deflate + Content-Type: + - application/json + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Content-Length: + - '358' + Content-Type: + - application/json + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Gdc-Cancel-Token: + - 9dc6944c-e0f2-45e6-afc3-0b2276c397e1 + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + executionResponse: + dimensions: + - headers: [] + localIdentifier: dim_0 + - headers: + - measureGroupHeaders: + - localIdentifier: total_revenue + format: $#,##0 + name: Total Revenue + localIdentifier: dim_1 + links: + executionResult: fb332d669c2540bc879f8591143bc142be634d42:5799a5b2a3489935b1e062ecdac565402623417d73ae07b4fe00c467bbfcb017 + - request: + method: POST + uri: http://localhost:3000/api/v1/actions/workspaces/demo_testing/ai/chatHistory + body: + reset: true + headers: + Accept: + - application/json + Accept-Encoding: + - br, gzip, deflate + Content-Type: + - application/json + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Content-Length: + - '51' + Content-Type: + - application/json + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + interactions: [] + threadId: demo_testing.admin + - request: + method: GET + uri: http://localhost:3000/api/v1/entities/workspaces?include=workspaces&page=0&size=500 + body: null + headers: + Accept: + - application/vnd.gooddata.api+json + Accept-Encoding: + - br, gzip, deflate + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Content-Length: + - '1274' + Content-Type: + - application/vnd.gooddata.api+json + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + data: + - id: demo + type: workspace + attributes: + name: Demo + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo + - id: demo_testing + type: workspace + attributes: + name: demo_testing + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo_testing + - id: demo_west + type: workspace + attributes: + name: Demo West + relationships: + parent: + data: + id: demo + type: workspace + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo_west + - id: demo_west_california + type: workspace + attributes: + name: Demo West California + relationships: + parent: + data: + id: demo_west + type: workspace + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo_west_california + included: + - id: demo + type: workspace + attributes: + name: Demo + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo + - id: demo_west + type: workspace + attributes: + name: Demo West + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo_west + links: + self: http://localhost:3000/api/v1/entities/workspaces?include=workspaces&page=0&size=500 + next: http://localhost:3000/api/v1/entities/workspaces?include=workspaces&page=1&size=500 + - request: + method: DELETE + uri: http://localhost:3000/api/v1/entities/workspaces/demo_testing + body: null + headers: + Accept-Encoding: + - br, gzip, deflate + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 204 + message: No Content + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: '' diff --git a/gooddata-sdk/tests/compute/test_compute_service.py b/gooddata-sdk/tests/compute/test_compute_service.py index a2d59743b..dd231d57d 100644 --- a/gooddata-sdk/tests/compute/test_compute_service.py +++ b/gooddata-sdk/tests/compute/test_compute_service.py @@ -182,3 +182,24 @@ def test_ai_chat_stream(test_config): finally: sdk.compute.reset_ai_chat_history(test_workspace_id) sdk.catalog_workspace.delete_workspace(test_workspace_id) + + +@gd_vcr.use_cassette(str(_fixtures_dir / "build_exec_def_from_chat_result.yaml")) +def test_build_exec_def_from_chat_result(test_config): + """Test build execution definition from chat result.""" + sdk = GoodDataSdk.create(host_=test_config["host"], token_=test_config["token"]) + path = _current_dir / "load" / "ai" + test_workspace_id = test_config["workspace_test"] + + try: + _setup_test_workspace(sdk, test_workspace_id, path) + response = sdk.compute.ai_chat(test_workspace_id, "What is the total revenue for the year 2024?") + execution_definition = sdk.compute.build_exec_def_from_chat_result(response) + assert execution_definition is not None + + execution = sdk.compute.for_exec_def(test_workspace_id, execution_definition) + assert execution.result_id is not None + + finally: + sdk.compute.reset_ai_chat_history(test_workspace_id) + sdk.catalog_workspace.delete_workspace(test_workspace_id) From c6a6b543ac513fbc7975b3d31726772196b8cda3 Mon Sep 17 00:00:00 2001 From: "Marcelo G. Almiron" Date: Wed, 28 May 2025 14:23:59 +0200 Subject: [PATCH 2/5] test: Add model to build fresh workspace jira: GDAI-238 risk: low --- .../b2f2d436-9831-4fe0-81df-8c59fd33242b.yaml | 194 ++++++++++++++++++ .../4717b786-2c2e-4596-adb5-4f8b0ab0e19a.yaml | 22 ++ .../9f2b1f37-befa-450e-a6cc-dc576845c412.yaml | 12 ++ .../metrics/amount_of_active_customers.yaml | 7 + .../metrics/amount_of_orders.yaml | 7 + .../metrics/amount_of_top_customers.yaml | 8 + .../metrics/amount_of_valid_orders.yaml | 8 + .../metrics/campaign_spend.yaml | 7 + .../analytics_model/metrics/order_amount.yaml | 7 + .../metrics/percent_revenue.yaml | 7 + ...percent_revenue_from_top_10_customers.yaml | 8 + ...revenue_from_top_10_percent_customers.yaml | 8 + ..._revenue_from_top_10_percent_products.yaml | 8 + .../percent_revenue_from_top_10_products.yaml | 8 + .../metrics/percent_revenue_in_category.yaml | 8 + .../metrics/percent_revenue_per_product.yaml | 7 + .../metrics/revenue-clothing.yaml | 7 + .../metrics/revenue-electronic.yaml | 7 + .../analytics_model/metrics/revenue-home.yaml | 7 + .../metrics/revenue-outdoor.yaml | 7 + .../ai/analytics_model/metrics/revenue.yaml | 8 + .../metrics/revenue_per_customer.yaml | 7 + .../metrics/revenue_per_dollar_spent.yaml | 7 + .../metrics/revenue_top_10.yaml | 7 + .../metrics/revenue_top_10_percent.yaml | 7 + .../metrics/total_revenue-no_filters.yaml | 7 + .../metrics/total_revenue.yaml | 7 + .../visualization_objects/campaign_spend.yaml | 62 ++++++ .../customers_trend.yaml | 74 +++++++ ..._per_product_by_customer_and_category.yaml | 77 +++++++ .../percentage_of_customers_by_region.yaml | 57 +++++ .../product_breakdown.yaml | 55 +++++ .../product_categories_pie_chart.yaml | 50 +++++ ...venue_comparison-over_previous_period.yaml | 73 +++++++ .../product_saleability.yaml | 55 +++++ ..._and_quantity_by_product_and_category.yaml | 97 +++++++++ .../revenue_by_category_trend.yaml | 54 +++++ .../revenue_by_product.yaml | 37 ++++ .../revenue_per_usd_vs_spend_by_campaign.yaml | 54 +++++ .../visualization_objects/revenue_trend.yaml | 66 ++++++ .../top_10_customers.yaml | 55 +++++ .../top_10_products.yaml | 55 +++++ .../ai/ldm/datasets/campaign_channels.yaml | 67 ++++++ .../load/ai/ldm/datasets/campaigns.yaml | 35 ++++ .../load/ai/ldm/datasets/customers.yaml | 58 ++++++ .../load/ai/ldm/datasets/order_lines.yaml | 108 ++++++++++ .../load/ai/ldm/datasets/products.yaml | 43 ++++ .../load/ai/ldm/date_instances/date.yaml | 15 ++ 48 files changed, 1651 insertions(+) create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/analytical_dashboards/b2f2d436-9831-4fe0-81df-8c59fd33242b.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/filter_contexts/4717b786-2c2e-4596-adb5-4f8b0ab0e19a.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/filter_contexts/9f2b1f37-befa-450e-a6cc-dc576845c412.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_active_customers.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_orders.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_top_customers.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_valid_orders.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/campaign_spend.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/order_amount.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_customers.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_percent_customers.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_percent_products.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_products.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_in_category.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_per_product.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-clothing.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-electronic.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-home.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-outdoor.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_per_customer.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_per_dollar_spent.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_top_10.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_top_10_percent.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/total_revenue-no_filters.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/total_revenue.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/campaign_spend.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/customers_trend.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/percent_revenue_per_product_by_customer_and_category.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/percentage_of_customers_by_region.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_breakdown.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_categories_pie_chart.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_revenue_comparison-over_previous_period.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_saleability.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_and_quantity_by_product_and_category.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_by_category_trend.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_by_product.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_per_usd_vs_spend_by_campaign.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_trend.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/top_10_customers.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/top_10_products.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/campaign_channels.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/campaigns.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/customers.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/order_lines.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/products.yaml create mode 100644 gooddata-pandas/tests/dataframe/load/ai/ldm/date_instances/date.yaml diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/analytical_dashboards/b2f2d436-9831-4fe0-81df-8c59fd33242b.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/analytical_dashboards/b2f2d436-9831-4fe0-81df-8c59fd33242b.yaml new file mode 100644 index 000000000..ef4dfab69 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/analytical_dashboards/b2f2d436-9831-4fe0-81df-8c59fd33242b.yaml @@ -0,0 +1,194 @@ +# (C) 2025 GoodData Corporation +content: + filterContextRef: + identifier: + id: 4717b786-2c2e-4596-adb5-4f8b0ab0e19a + type: filterContext + layout: + sections: + - header: + description: All in one description + title: All in one title + items: + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: top_10_customers + type: visualizationObject + localIdentifier: 2c7400ac-5f63-46f8-aa12-a2debe13fd14 + properties: {} + title: Top 10 Customers + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: revenue_by_product + type: visualizationObject + localIdentifier: a50daab7-fb78-45eb-a2b4-d5cc8cbd89e9 + properties: {} + title: Revenue by Product + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: revenue_by_category_trend + type: visualizationObject + localIdentifier: efccc783-5896-4eb6-890f-2e51ece3f159 + properties: {} + title: Revenue by Category Trend + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: product_saleability + type: visualizationObject + localIdentifier: d738d85f-e935-4e2c-b8b4-a8b456f55079 + properties: {} + title: Product Saleability + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: product_categories_pie_chart + type: visualizationObject + localIdentifier: 8c194c85-bad6-42da-b4e3-08d270278316 + properties: {} + title: Product Categories Pie Chart + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: percentage_of_customers_by_region + type: visualizationObject + localIdentifier: 2c3307b2-581f-4bab-9252-6b5279565b24 + properties: {} + title: Percentage of Customers by Region + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: customers_trend + type: visualizationObject + localIdentifier: 87505bb0-d954-4add-811d-f4e75e431660 + properties: {} + title: Customers Trend + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: campaign_spend + type: visualizationObject + localIdentifier: 0cb01f6a-6ea6-4c22-bb12-ded00a9eac66 + properties: {} + title: Campaign Spend + type: insight + - size: + xl: + gridWidth: 12 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: percent_revenue_per_product_by_customer_and_category + type: visualizationObject + localIdentifier: 2213d6e4-6df7-458e-806d-f02bae5ce66a + properties: {} + title: '% Revenue per Product by Customer and Category' + type: insight + type: IDashboardLayoutSection + type: IDashboardLayout + version: '2' +description: '' +id: b2f2d436-9831-4fe0-81df-8c59fd33242b +title: All visualizations 1 with custom filter diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/filter_contexts/4717b786-2c2e-4596-adb5-4f8b0ab0e19a.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/filter_contexts/4717b786-2c2e-4596-adb5-4f8b0ab0e19a.yaml new file mode 100644 index 000000000..852c92031 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/filter_contexts/4717b786-2c2e-4596-adb5-4f8b0ab0e19a.yaml @@ -0,0 +1,22 @@ +# (C) 2025 GoodData Corporation +content: + filters: + - attributeFilter: + attributeElements: + uris: + - Biolid + - ChalkTalk + - Compglass + - Elentrix + displayForm: + identifier: + id: product_name + type: label + filterElementsBy: [] + localIdentifier: 6b94bbb585d44c79967867719e524fae + negativeSelection: false + selectionMode: multi + version: '2' +description: '' +id: 4717b786-2c2e-4596-adb5-4f8b0ab0e19a +title: filterContext diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/filter_contexts/9f2b1f37-befa-450e-a6cc-dc576845c412.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/filter_contexts/9f2b1f37-befa-450e-a6cc-dc576845c412.yaml new file mode 100644 index 000000000..8ec1d3ebb --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/filter_contexts/9f2b1f37-befa-450e-a6cc-dc576845c412.yaml @@ -0,0 +1,12 @@ +# (C) 2025 GoodData Corporation +content: + filters: + - dateFilter: + from: '0' + granularity: GDC.time.year + to: '0' + type: relative + version: '2' +description: '' +id: 9f2b1f37-befa-450e-a6cc-dc576845c412 +title: filterContext diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_active_customers.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_active_customers.yaml new file mode 100644 index 000000000..1dfb3eff8 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_active_customers.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: '#,##0' + maql: SELECT COUNT({attribute/customer_id},{attribute/order_line_id}) +description: '' +id: amount_of_active_customers +title: '# of Active Customers' diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_orders.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_orders.yaml new file mode 100644 index 000000000..73bc6a977 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_orders.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: '#,##0' + maql: SELECT COUNT({attribute/order_id}) +description: '' +id: amount_of_orders +title: '# of Orders' diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_top_customers.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_top_customers.yaml new file mode 100644 index 000000000..bc2547333 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_top_customers.yaml @@ -0,0 +1,8 @@ +# (C) 2025 GoodData Corporation +content: + format: '#,##0' + maql: 'SELECT {metric/amount_of_active_customers} WHERE (SELECT {metric/revenue} + BY {attribute/customer_id}) > 10000 ' +description: '' +id: amount_of_top_customers +title: '# of Top Customers' diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_valid_orders.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_valid_orders.yaml new file mode 100644 index 000000000..35a719267 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/amount_of_valid_orders.yaml @@ -0,0 +1,8 @@ +# (C) 2025 GoodData Corporation +content: + format: '#,##0.00' + maql: SELECT {metric/amount_of_orders} WHERE NOT ({label/order_status} IN ("null", + "Returned", "Canceled")) +description: '' +id: amount_of_valid_orders +title: '# of Valid Orders' diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/campaign_spend.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/campaign_spend.yaml new file mode 100644 index 000000000..93f99d910 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/campaign_spend.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: $#,##0 + maql: SELECT SUM({fact/spend}) +description: '' +id: campaign_spend +title: Campaign Spend diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/order_amount.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/order_amount.yaml new file mode 100644 index 000000000..ca0efae86 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/order_amount.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: $#,##0 + maql: SELECT SUM({fact/price}*{fact/quantity}) +description: '' +id: order_amount +title: Order Amount diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue.yaml new file mode 100644 index 000000000..c52541fa4 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: '#,##0.0%' + maql: SELECT {metric/revenue} / {metric/total_revenue} +description: '' +id: percent_revenue +title: '% Revenue' diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_customers.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_customers.yaml new file mode 100644 index 000000000..13ac3c103 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_customers.yaml @@ -0,0 +1,8 @@ +# (C) 2025 GoodData Corporation +content: + format: '#,##0.0%' + maql: "SELECT\n (SELECT {metric/revenue} WHERE (SELECT {metric/revenue_top_10} BY\ + \ {attribute/customer_id}) > 0)\n /\n {metric/revenue}" +description: '' +id: percent_revenue_from_top_10_customers +title: '% Revenue from Top 10 Customers' diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_percent_customers.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_percent_customers.yaml new file mode 100644 index 000000000..514f4e13e --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_percent_customers.yaml @@ -0,0 +1,8 @@ +# (C) 2025 GoodData Corporation +content: + format: '#,##0.0%' + maql: "SELECT\n (SELECT {metric/revenue} WHERE (SELECT {metric/revenue_top_10_percent}\ + \ BY {attribute/customer_id}) > 0)\n /\n {metric/revenue}" +description: '' +id: percent_revenue_from_top_10_percent_customers +title: '% Revenue from Top 10% Customers' diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_percent_products.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_percent_products.yaml new file mode 100644 index 000000000..962393d29 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_percent_products.yaml @@ -0,0 +1,8 @@ +# (C) 2025 GoodData Corporation +content: + format: '#,##0.0%' + maql: "SELECT\n (SELECT {metric/revenue} WHERE (SELECT {metric/revenue_top_10_percent}\ + \ BY {attribute/product_id}) > 0)\n /\n {metric/revenue}" +description: '' +id: percent_revenue_from_top_10_percent_products +title: '% Revenue from Top 10% Products' diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_products.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_products.yaml new file mode 100644 index 000000000..4f825ef41 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_from_top_10_products.yaml @@ -0,0 +1,8 @@ +# (C) 2025 GoodData Corporation +content: + format: '#,##0.0%' + maql: "SELECT\n (SELECT {metric/revenue} WHERE (SELECT {metric/revenue_top_10} BY\ + \ {attribute/product_id}) > 0)\n /\n {metric/revenue}" +description: '' +id: percent_revenue_from_top_10_products +title: '% Revenue from Top 10 Products' diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_in_category.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_in_category.yaml new file mode 100644 index 000000000..491f870b0 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_in_category.yaml @@ -0,0 +1,8 @@ +# (C) 2025 GoodData Corporation +content: + format: '#,##0.0%' + maql: SELECT {metric/revenue} / (SELECT {metric/revenue} BY {attribute/products.category}, + ALL OTHER) +description: '' +id: percent_revenue_in_category +title: '% Revenue in Category' diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_per_product.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_per_product.yaml new file mode 100644 index 000000000..1d8d1e0fc --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/percent_revenue_per_product.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: '#,##0.0%' + maql: SELECT {metric/revenue} / (SELECT {metric/revenue} BY ALL {attribute/product_id}) +description: '' +id: percent_revenue_per_product +title: '% Revenue per Product' diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-clothing.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-clothing.yaml new file mode 100644 index 000000000..ee50ebe45 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-clothing.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE {label/products.category} IN ("Clothing") +description: '' +id: revenue-clothing +title: Revenue (Clothing) diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-electronic.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-electronic.yaml new file mode 100644 index 000000000..bf706b4f0 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-electronic.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE {label/products.category} IN ( "Electronics") +description: '' +id: revenue-electronic +title: Revenue (Electronic) diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-home.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-home.yaml new file mode 100644 index 000000000..6521c722d --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-home.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE {label/products.category} IN ("Home") +description: '' +id: revenue-home +title: Revenue (Home) diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-outdoor.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-outdoor.yaml new file mode 100644 index 000000000..92af3b14a --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue-outdoor.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE {label/products.category} IN ("Outdoor") +description: '' +id: revenue-outdoor +title: Revenue (Outdoor) diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue.yaml new file mode 100644 index 000000000..278fc315d --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue.yaml @@ -0,0 +1,8 @@ +# (C) 2025 GoodData Corporation +content: + format: $#,##0 + maql: SELECT {metric/order_amount} WHERE NOT ({label/order_status} IN ("null", "Returned", + "Canceled")) +description: '' +id: revenue +title: Revenue diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_per_customer.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_per_customer.yaml new file mode 100644 index 000000000..6815dc309 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_per_customer.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: $#,##0.0 + maql: SELECT AVG(SELECT {metric/revenue} BY {attribute/customer_id}) +description: '' +id: revenue_per_customer +title: Revenue per Customer diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_per_dollar_spent.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_per_dollar_spent.yaml new file mode 100644 index 000000000..01c0ac775 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_per_dollar_spent.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: $#,##0.0 + maql: SELECT {metric/revenue} / {metric/campaign_spend} +description: '' +id: revenue_per_dollar_spent +title: Revenue per Dollar Spent diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_top_10.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_top_10.yaml new file mode 100644 index 000000000..fd92065fe --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_top_10.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE TOP(10) OF ({metric/revenue}) +description: '' +id: revenue_top_10 +title: Revenue / Top 10 diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_top_10_percent.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_top_10_percent.yaml new file mode 100644 index 000000000..ffae3797b --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/revenue_top_10_percent.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE TOP(10%) OF ({metric/revenue}) +description: '' +id: revenue_top_10_percent +title: Revenue / Top 10% diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/total_revenue-no_filters.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/total_revenue-no_filters.yaml new file mode 100644 index 000000000..7b29ce6b6 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/total_revenue-no_filters.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: $#,##0 + maql: SELECT {metric/total_revenue} WITHOUT PARENT FILTER +description: '' +id: total_revenue-no_filters +title: Total Revenue (No Filters) diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/total_revenue.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/total_revenue.yaml new file mode 100644 index 000000000..30d1cebf0 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/metrics/total_revenue.yaml @@ -0,0 +1,7 @@ +# (C) 2025 GoodData Corporation +content: + format: $#,##0 + maql: SELECT {metric/revenue} BY ALL OTHER +description: '' +id: total_revenue +title: Total Revenue diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/campaign_spend.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/campaign_spend.yaml new file mode 100644 index 000000000..e4bccc985 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/campaign_spend.yaml @@ -0,0 +1,62 @@ +# (C) 2025 GoodData Corporation +content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: campaign_spend + type: metric + localIdentifier: d319bcb2d8c04442a684e3b3cd063381 + title: Campaign Spend + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: campaign_channels.category + type: label + localIdentifier: 291c085e7df8420db84117ca49f59c49 + localIdentifier: view + - items: + - attribute: + displayForm: + identifier: + id: campaign_name + type: label + localIdentifier: d9dd143d647d4d148405a60ec2cf59bc + localIdentifier: segment + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: type + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: campaign_channels.category + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: campaign_name + type: label + notIn: + values: [] + properties: + controls: + legend: + position: bottom + version: '2' + visualizationUrl: local:treemap +description: '' +id: campaign_spend +title: Campaign Spend diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/customers_trend.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/customers_trend.yaml new file mode 100644 index 000000000..b74740893 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/customers_trend.yaml @@ -0,0 +1,74 @@ +# (C) 2025 GoodData Corporation +content: + buckets: + - items: + - measure: + alias: Active Customers + definition: + measureDefinition: + computeRatio: false + filters: [] + item: + identifier: + id: amount_of_active_customers + type: metric + localIdentifier: 2ba0b87b59ca41a4b1530e81a5c1d081 + title: '# of Active Customers' + localIdentifier: measures + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue_per_customer + type: metric + localIdentifier: ec0606894b9f4897b7beaf1550608928 + title: Revenue per Customer + localIdentifier: secondary_measures + - items: + - attribute: + displayForm: + identifier: + id: date.month + type: label + localIdentifier: 0de7d7f08af7480aa636857a26be72b6 + localIdentifier: view + filters: + - relativeDateFilter: + dataSet: + identifier: + id: date + type: dataset + from: -11 + granularity: GDC.time.month + to: 0 + properties: + controls: + colorMapping: + - color: + type: guid + value: '20' + id: 2ba0b87b59ca41a4b1530e81a5c1d081 + - color: + type: guid + value: '4' + id: ec0606894b9f4897b7beaf1550608928 + dualAxis: true + legend: + position: bottom + primaryChartType: column + secondaryChartType: line + secondary_yaxis: + measures: + - ec0606894b9f4897b7beaf1550608928 + xaxis: + name: + visible: false + rotation: auto + version: '2' + visualizationUrl: local:combo2 +description: '' +id: customers_trend +title: Customers Trend diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/percent_revenue_per_product_by_customer_and_category.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/percent_revenue_per_product_by_customer_and_category.yaml new file mode 100644 index 000000000..ad33a7fca --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/percent_revenue_per_product_by_customer_and_category.yaml @@ -0,0 +1,77 @@ +# (C) 2025 GoodData Corporation +content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: percent_revenue_per_product + type: metric + localIdentifier: 08d8346c1ce7438994b251991c0fbf65 + title: '% Revenue per Product' + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: b2350c06688b4da9b3833ebcce65527f + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: customer_name + type: label + localIdentifier: 7a4045fd00ac44579f52406df679435f + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: 6a003ffd14994237ba64c4a02c488429 + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: 75ea396d0c8b48098e31dccf8b5801d3 + localIdentifier: attribute + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: customer_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + properties: + sortItems: + - attributeSortItem: + attributeIdentifier: 7a4045fd00ac44579f52406df679435f + direction: asc + version: '2' + visualizationUrl: local:table +description: '' +id: percent_revenue_per_product_by_customer_and_category +title: '% Revenue per Product by Customer and Category' diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/percentage_of_customers_by_region.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/percentage_of_customers_by_region.yaml new file mode 100644 index 000000000..6f57db4f0 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/percentage_of_customers_by_region.yaml @@ -0,0 +1,57 @@ +# (C) 2025 GoodData Corporation +content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: amount_of_active_customers + type: metric + localIdentifier: 1a14cdc1293c46e89a2e25d3e741d235 + title: '# of Active Customers' + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: date.month + type: label + localIdentifier: c1feca1864244ec2ace7a9b9d7fda231 + localIdentifier: view + - items: + - attribute: + displayForm: + identifier: + id: region + type: label + localIdentifier: 530cddbd7ca04d039e73462d81ed44d5 + localIdentifier: stack + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: region + type: label + notIn: + values: [] + - relativeDateFilter: + dataSet: + identifier: + id: date + type: dataset + from: -11 + granularity: GDC.time.month + to: 0 + properties: + controls: + legend: + position: bottom + stackMeasuresToPercent: true + version: '2' + visualizationUrl: local:area +description: '' +id: percentage_of_customers_by_region +title: Percentage of Customers by Region diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_breakdown.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_breakdown.yaml new file mode 100644 index 000000000..214952fda --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_breakdown.yaml @@ -0,0 +1,55 @@ +# (C) 2025 GoodData Corporation +content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 590d332ef686468b8878ae41b23341c6 + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: b166c71091864312a14c7ae8ff886ffe + localIdentifier: view + - items: + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: e920a50e0bbb49788df0aac53634c1cd + localIdentifier: segment + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + properties: + controls: + legend: + position: bottom + version: '2' + visualizationUrl: local:treemap +description: '' +id: product_breakdown +title: Product Breakdown diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_categories_pie_chart.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_categories_pie_chart.yaml new file mode 100644 index 000000000..247c8983b --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_categories_pie_chart.yaml @@ -0,0 +1,50 @@ +# (C) 2025 GoodData Corporation +content: + buckets: + - items: + - measure: + definition: + measureDefinition: + computeRatio: true + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 162b857af49d45769bc12604a5c192b9 + title: '% Revenue' + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: fe513cef1c6244a5ac21c5f49c56b108 + localIdentifier: view + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + properties: + controls: + dataLabels: + visible: auto + legend: + position: bottom + version: '2' + visualizationUrl: local:donut +description: '' +id: product_categories_pie_chart +title: Product Categories Pie Chart diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_revenue_comparison-over_previous_period.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_revenue_comparison-over_previous_period.yaml new file mode 100644 index 000000000..697db6ce5 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_revenue_comparison-over_previous_period.yaml @@ -0,0 +1,73 @@ +# (C) 2025 GoodData Corporation +content: + buckets: + - items: + - measure: + alias: Previous Period + definition: + popMeasureDefinition: + measureIdentifier: c82e025fa2db4afea9a600a424591dbe + popAttribute: + identifier: + id: date.year + type: label + localIdentifier: c82e025fa2db4afea9a600a424591dbe_pop + - measure: + alias: This Period + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: c82e025fa2db4afea9a600a424591dbe + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: c804ef5ba7944a5a9f360c86a9e95e9a + localIdentifier: view + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + - relativeDateFilter: + dataSet: + identifier: + id: date + type: dataset + from: -11 + granularity: GDC.time.month + to: 0 + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + properties: + controls: + legend: + position: bottom + stackMeasures: false + xaxis: + name: + visible: false + yaxis: + name: + visible: false + version: '2' + visualizationUrl: local:column +description: '' +id: product_revenue_comparison-over_previous_period +title: Product Revenue Comparison (over previous period) diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_saleability.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_saleability.yaml new file mode 100644 index 000000000..205996760 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/product_saleability.yaml @@ -0,0 +1,55 @@ +# (C) 2025 GoodData Corporation +content: + buckets: + - items: + - measure: + alias: Number of Orders + definition: + measureDefinition: + filters: [] + item: + identifier: + id: amount_of_orders + type: metric + localIdentifier: aeb5d51a162d4b59aba3bd6ddebcc780 + title: '# of Orders' + localIdentifier: measures + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 94b3edd3a73c4a48a4d13bbe9442cc98 + title: Revenue + localIdentifier: secondary_measures + - items: + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: d2a991bdd123448eb2be73d79f1180c4 + localIdentifier: attribute + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + properties: + controls: + dataLabels: + visible: auto + grid: + enabled: true + version: '2' + visualizationUrl: local:scatter +description: '' +id: product_saleability +title: Product Saleability diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_and_quantity_by_product_and_category.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_and_quantity_by_product_and_category.yaml new file mode 100644 index 000000000..e63f146b6 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_and_quantity_by_product_and_category.yaml @@ -0,0 +1,97 @@ +# (C) 2025 GoodData Corporation +content: + buckets: + - items: + - measure: + alias: Items Sold + definition: + measureDefinition: + aggregation: sum + filters: [] + item: + identifier: + id: quantity + type: fact + format: '#,##0.00' + localIdentifier: 29486504dd0e4a36a18b0b2f792d3a46 + title: Sum of Quantity + - measure: + definition: + measureDefinition: + aggregation: avg + filters: [] + item: + identifier: + id: price + type: fact + format: '#,##0.00' + localIdentifier: aa6391acccf1452f8011201aef9af492 + title: Avg Price + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: percent_revenue_in_category + type: metric + localIdentifier: 2cd39539d8da46c9883e63caa3ba7cc0 + title: '% Revenue in Category' + - measure: + alias: Total Revenue + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 9a0f08331c094c7facf2a0b4f418de0a + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: 06bc6b3b9949466494e4f594c11f1bff + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: 192668bfb6a74e9ab7b5d1ce7cb68ea3 + localIdentifier: attribute + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: customer_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + properties: + sortItems: + - attributeSortItem: + attributeIdentifier: 06bc6b3b9949466494e4f594c11f1bff + direction: asc + version: '2' + visualizationUrl: local:table +description: '' +id: revenue_and_quantity_by_product_and_category +title: Revenue and Quantity by Product and Category diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_by_category_trend.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_by_category_trend.yaml new file mode 100644 index 000000000..5c3221033 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_by_category_trend.yaml @@ -0,0 +1,54 @@ +# (C) 2025 GoodData Corporation +content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 7df6c34387744d69b23ec92e1a5cf543 + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: date.month + type: label + localIdentifier: 4bb4fc1986c546de9ad976e6ec23fed4 + localIdentifier: trend + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: 34bddcb1cd024902a82396216b0fa9d8 + localIdentifier: segment + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + - relativeDateFilter: + dataSet: + identifier: + id: date + type: dataset + granularity: GDC.time.year + properties: + controls: + legend: + position: bottom + version: '2' + visualizationUrl: local:line +description: '' +id: revenue_by_category_trend +title: Revenue by Category Trend diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_by_product.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_by_product.yaml new file mode 100644 index 000000000..520b12972 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_by_product.yaml @@ -0,0 +1,37 @@ +# (C) 2025 GoodData Corporation +content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 4ae3401bdbba4938afe983df4ba04e1c + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: 1c8ba72dbfc84ddd913bf81dc355c427 + localIdentifier: view + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + properties: {} + version: '2' + visualizationUrl: local:bar +description: '' +id: revenue_by_product +title: Revenue by Product diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_per_usd_vs_spend_by_campaign.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_per_usd_vs_spend_by_campaign.yaml new file mode 100644 index 000000000..6d0f7cbde --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_per_usd_vs_spend_by_campaign.yaml @@ -0,0 +1,54 @@ +# (C) 2025 GoodData Corporation +content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: campaign_spend + type: metric + localIdentifier: 13a50d811e474ac6808d8da7f4673b35 + title: Campaign Spend + localIdentifier: measures + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue_per_dollar_spent + type: metric + localIdentifier: a0f15e82e6334280a44dbedc7d086e7c + title: Revenue per Dollar Spent + localIdentifier: secondary_measures + - items: + - attribute: + displayForm: + identifier: + id: campaign_name + type: label + localIdentifier: 1d9fa968bafb423eb29c938dfb1207ff + localIdentifier: attribute + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: campaign_name + type: label + notIn: + values: [] + properties: + controls: + xaxis: + min: '0' + yaxis: + min: '0' + version: '2' + visualizationUrl: local:scatter +description: '' +id: revenue_per_usd_vs_spend_by_campaign +title: Revenue per $ vs Spend by Campaign diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_trend.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_trend.yaml new file mode 100644 index 000000000..e0ded10f3 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/revenue_trend.yaml @@ -0,0 +1,66 @@ +# (C) 2025 GoodData Corporation +content: + buckets: + - items: + - measure: + definition: + measureDefinition: + computeRatio: false + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 60c854969a9c4c278ab596d99c222e92 + title: Revenue + localIdentifier: measures + - items: + - measure: + alias: Number of Orders + definition: + measureDefinition: + computeRatio: false + filters: [] + item: + identifier: + id: amount_of_orders + type: metric + localIdentifier: c2fa7ef48cc54af99f8c280eb451e051 + title: '# of Orders' + localIdentifier: secondary_measures + - items: + - attribute: + displayForm: + identifier: + id: date.month + type: label + localIdentifier: 413ac374b65648fa96826ca01d47bdda + localIdentifier: view + filters: + - relativeDateFilter: + dataSet: + identifier: + id: date + type: dataset + from: -3 + granularity: GDC.time.quarter + to: 0 + properties: + controls: + dualAxis: true + legend: + position: bottom + primaryChartType: column + secondaryChartType: line + secondary_yaxis: + measures: + - c2fa7ef48cc54af99f8c280eb451e051 + xaxis: + name: + visible: false + rotation: auto + version: '2' + visualizationUrl: local:combo2 +description: '' +id: revenue_trend +title: Revenue Trend diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/top_10_customers.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/top_10_customers.yaml new file mode 100644 index 000000000..9a191a086 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/top_10_customers.yaml @@ -0,0 +1,55 @@ +# (C) 2025 GoodData Corporation +content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue_top_10 + type: metric + localIdentifier: 3f127ccfe57a40399e23f9ae2a4ad810 + title: Revenue / Top 10 + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: customer_name + type: label + localIdentifier: f4e39e24f11e4827a191c30d65c89d2c + localIdentifier: view + - items: + - attribute: + displayForm: + identifier: + id: state + type: label + localIdentifier: bbccd430176d428caed54c99afc9589e + localIdentifier: stack + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: customer_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: state + type: label + notIn: + values: [] + properties: + controls: + legend: + position: bottom + version: '2' + visualizationUrl: local:bar +description: '' +id: top_10_customers +title: Top 10 Customers diff --git a/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/top_10_products.yaml b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/top_10_products.yaml new file mode 100644 index 000000000..c5f39d2ec --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/analytics_model/visualization_objects/top_10_products.yaml @@ -0,0 +1,55 @@ +# (C) 2025 GoodData Corporation +content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue_top_10 + type: metric + localIdentifier: 77dc71bbac92412bac5f94284a5919df + title: Revenue / Top 10 + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: 781952e728204dcf923142910cc22ae2 + localIdentifier: view + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: fe513cef1c6244a5ac21c5f49c56b108 + localIdentifier: stack + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + properties: + controls: + legend: + position: bottom + version: '2' + visualizationUrl: local:bar +description: '' +id: top_10_products +title: Top 10 Products diff --git a/gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/campaign_channels.yaml b/gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/campaign_channels.yaml new file mode 100644 index 000000000..e97992521 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/campaign_channels.yaml @@ -0,0 +1,67 @@ +# (C) 2025 GoodData Corporation +attributes: + - description: Campaign channel id + id: campaign_channel_id + labels: [] + sourceColumn: campaign_channel_id + sourceColumnDataType: STRING + tags: + - Campaign channels + title: Campaign channel id + - description: Category + id: campaign_channels.category + labels: [] + sourceColumn: category + sourceColumnDataType: STRING + tags: + - Campaign channels + title: Category + - description: Type + id: type + labels: [] + sourceColumn: type + sourceColumnDataType: STRING + tags: + - Campaign channels + title: Type +dataSourceTableId: + dataSourceId: pg_local_docker-demo + id: campaign_channels + path: + - demo_6d9051d9069a8468 + - campaign_channels + type: dataSource +description: Campaign channels +facts: + - description: Budget + id: budget + sourceColumn: budget + sourceColumnDataType: NUMERIC + tags: + - Campaign channels + title: Budget + - description: Spend + id: spend + sourceColumn: spend + sourceColumnDataType: NUMERIC + tags: + - Campaign channels + title: Spend +grain: + - id: campaign_channel_id + type: attribute +id: campaign_channels +references: + - identifier: + id: campaigns + type: dataset + multivalue: false + sources: + - column: campaign_id + dataType: INT + target: + id: campaign_id + type: attribute +tags: + - Campaign channels +title: Campaign channels diff --git a/gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/campaigns.yaml b/gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/campaigns.yaml new file mode 100644 index 000000000..9e66fc8ff --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/campaigns.yaml @@ -0,0 +1,35 @@ +# (C) 2025 GoodData Corporation +attributes: + - description: Campaign id + id: campaign_id + labels: [] + sourceColumn: campaign_id + sourceColumnDataType: INT + tags: + - Campaigns + title: Campaign id + - description: Campaign name + id: campaign_name + labels: [] + sourceColumn: campaign_name + sourceColumnDataType: STRING + tags: + - Campaigns + title: Campaign name +dataSourceTableId: + dataSourceId: pg_local_docker-demo + id: campaigns + path: + - demo_6d9051d9069a8468 + - campaigns + type: dataSource +description: Campaigns +facts: [] +grain: + - id: campaign_id + type: attribute +id: campaigns +references: [] +tags: + - Campaigns +title: Campaigns diff --git a/gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/customers.yaml b/gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/customers.yaml new file mode 100644 index 000000000..031777a44 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/customers.yaml @@ -0,0 +1,58 @@ +# (C) 2025 GoodData Corporation +attributes: + - description: Customer id + id: customer_id + labels: [] + sourceColumn: customer_id + sourceColumnDataType: INT + tags: + - Customers + title: Customer id + - description: Customer name + id: customer_name + labels: [] + sourceColumn: customer_name + sourceColumnDataType: STRING + tags: + - Customers + title: Customer name + - description: Region + id: region + labels: [] + sourceColumn: region + sourceColumnDataType: STRING + tags: + - Customers + title: Region + - description: State + id: state + labels: + - description: Location + id: geo__state__location + sourceColumn: geo__state__location + sourceColumnDataType: STRING + tags: + - Customers + title: Location + sourceColumn: state + sourceColumnDataType: STRING + tags: + - Customers + title: State +dataSourceTableId: + dataSourceId: pg_local_docker-demo + id: customers + path: + - demo_6d9051d9069a8468 + - customers + type: dataSource +description: Customers +facts: [] +grain: + - id: customer_id + type: attribute +id: customers +references: [] +tags: + - Customers +title: Customers diff --git a/gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/order_lines.yaml b/gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/order_lines.yaml new file mode 100644 index 000000000..c244ca158 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/order_lines.yaml @@ -0,0 +1,108 @@ +# (C) 2025 GoodData Corporation +attributes: + - description: Order id + id: order_id + labels: [] + sourceColumn: order_id + sourceColumnDataType: STRING + tags: + - Order lines + title: Order id + - description: Order line id + id: order_line_id + labels: [] + sourceColumn: order_line_id + sourceColumnDataType: STRING + tags: + - Order lines + title: Order line id + - description: Order status + id: order_status + labels: [] + sourceColumn: order_status + sourceColumnDataType: STRING + tags: + - Order lines + title: Order status +dataSourceTableId: + dataSourceId: pg_local_docker-demo + id: order_lines + path: + - demo_6d9051d9069a8468 + - order_lines + type: dataSource +description: Order lines +facts: + - description: Price + id: price + sourceColumn: price + sourceColumnDataType: NUMERIC + tags: + - Order lines + title: Price + - description: Quantity + id: quantity + sourceColumn: quantity + sourceColumnDataType: NUMERIC + tags: + - Order lines + title: Quantity +grain: + - id: order_line_id + type: attribute +id: order_lines +references: + - identifier: + id: campaigns + type: dataset + multivalue: false + sources: + - column: campaign_id + dataType: INT + target: + id: campaign_id + type: attribute + - identifier: + id: customers + type: dataset + multivalue: false + sources: + - column: customer_id + dataType: INT + target: + id: customer_id + type: attribute + - identifier: + id: date + type: dataset + multivalue: false + sources: + - column: date + dataType: DATE + target: + id: date + type: date + - identifier: + id: products + type: dataset + multivalue: false + sources: + - column: product_id + dataType: INT + target: + id: product_id + type: attribute +tags: + - Order lines +title: Order lines +workspaceDataFilterColumns: + - dataType: STRING + name: wdf__region + - dataType: STRING + name: wdf__state +workspaceDataFilterReferences: + - filterColumn: wdf__region + filterColumnDataType: STRING + filterId: + id: wdf__region + type: workspaceDataFilter diff --git a/gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/products.yaml b/gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/products.yaml new file mode 100644 index 000000000..2096de7ab --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/ldm/datasets/products.yaml @@ -0,0 +1,43 @@ +# (C) 2025 GoodData Corporation +attributes: + - description: Product id + id: product_id + labels: [] + sourceColumn: product_id + sourceColumnDataType: INT + tags: + - Products + title: Product id + - description: Product name + id: product_name + labels: [] + sourceColumn: product_name + sourceColumnDataType: STRING + tags: + - Products + title: Product name + - description: Category + id: products.category + labels: [] + sourceColumn: category + sourceColumnDataType: STRING + tags: + - Products + title: Category +dataSourceTableId: + dataSourceId: pg_local_docker-demo + id: products + path: + - demo_6d9051d9069a8468 + - products + type: dataSource +description: Products +facts: [] +grain: + - id: product_id + type: attribute +id: products +references: [] +tags: + - Products +title: Products diff --git a/gooddata-pandas/tests/dataframe/load/ai/ldm/date_instances/date.yaml b/gooddata-pandas/tests/dataframe/load/ai/ldm/date_instances/date.yaml new file mode 100644 index 000000000..5ba24d1a8 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/load/ai/ldm/date_instances/date.yaml @@ -0,0 +1,15 @@ +# (C) 2025 GoodData Corporation +description: '' +granularities: + - DAY + - WEEK + - MONTH + - QUARTER + - YEAR +granularitiesFormatting: + titleBase: '' + titlePattern: '%titleBase - %granularityTitle' +id: date +tags: + - Date +title: Date From 2a78f9faf52f7223e2fe35904f7a7cda4aca947a Mon Sep 17 00:00:00 2001 From: "Marcelo G. Almiron" Date: Wed, 28 May 2025 15:16:59 +0200 Subject: [PATCH 3/5] fix(ai): Use attribute id for label on SDK object jira: GDAI-238 risk: low --- .../compute/visualization_to_sdk_converter.py | 2 +- .../build_exec_def_from_chat_result.yaml | 124 ++++++++++-------- .../tests/compute/test_compute_service.py | 2 +- 3 files changed, 70 insertions(+), 58 deletions(-) diff --git a/gooddata-sdk/gooddata_sdk/compute/visualization_to_sdk_converter.py b/gooddata-sdk/gooddata_sdk/compute/visualization_to_sdk_converter.py index 70d88afd2..3221d395d 100644 --- a/gooddata-sdk/gooddata_sdk/compute/visualization_to_sdk_converter.py +++ b/gooddata-sdk/gooddata_sdk/compute/visualization_to_sdk_converter.py @@ -31,7 +31,7 @@ def convert_attribute(attr_dict: dict[str, Any]) -> Attribute: Attribute: An SDK Attribute object with local_id and label set """ local_id = attr_dict["id"] - label = attr_dict["title"] + label = attr_dict["id"] return Attribute(local_id=local_id, label=label) @staticmethod diff --git a/gooddata-sdk/tests/compute/fixtures/build_exec_def_from_chat_result.yaml b/gooddata-sdk/tests/compute/fixtures/build_exec_def_from_chat_result.yaml index b41154bd4..716fbf961 100644 --- a/gooddata-sdk/tests/compute/fixtures/build_exec_def_from_chat_result.yaml +++ b/gooddata-sdk/tests/compute/fixtures/build_exec_def_from_chat_result.yaml @@ -50,7 +50,7 @@ interactions: to access it. status: 404 title: Not Found - traceId: 85c696d39f778b59e3021bc8655c417c + traceId: 3078ca62b33d7fd01dc11b5be19dc230 - request: method: GET uri: http://localhost:3000/api/v1/entities/workspaces/demo_testing?include=workspaces @@ -99,7 +99,7 @@ interactions: to access it. status: 404 title: Not Found - traceId: 03937b37e651ec6d97d5d94df689ba7e + traceId: df2b4b72297902bf4813ef4961090443 - request: method: POST uri: http://localhost:3000/api/v1/entities/workspaces @@ -1864,7 +1864,7 @@ interactions: method: POST uri: http://localhost:3000/api/v1/actions/workspaces/demo_testing/ai/chat body: - question: What is the total revenue for the year 2024? + question: Display the revenue by product headers: Accept: - application/json @@ -1884,7 +1884,7 @@ interactions: Cache-Control: - no-cache, no-store, max-age=0, must-revalidate Content-Length: - - '856' + - '775' Content-Type: - application/json DATE: *id001 @@ -1916,70 +1916,67 @@ interactions: reasoning: Creating a new visualization ... createdVisualizations: objects: - - id: total_revenue_for_2024 - title: Total Revenue for 2024 - visualizationType: HEADLINE + - id: revenue_by_product + title: Revenue by Product + visualizationType: COLUMN metrics: - - id: total_revenue + - id: revenue type: metric - title: Total Revenue - dimensionality: [] - filters: - - using: date.year - include: - - '2024' + title: Revenue + dimensionality: + - id: product_name + type: attribute + title: Product name + filters: [] suggestions: - - query: Slice by 'Date - Month/Year' to see monthly revenue distribution - for 2024 - label: Slice by month/year - - query: Slice by 'Date - Quarter/Year' to see quarterly revenue - distribution for 2024 - label: Slice by quarter/year + - query: Slice by 'Category' + label: Slice by Category + - query: Switch to a table view for detailed comparison + label: Switch to Table View reasoning: ' - Here is a headline showing the Total Revenue for 2024. + Here is a column chart showing the Revenue by Product grouped by Product + name. - - Metrics: Total Revenue + - Metrics: Revenue - - Attributes: None + - Attributes: Product name - - Filter: Include Date. Year: 2024 + - Filter: None ' - chatHistoryInteractionId: bc57ccb7ee8f4eec8eed2da588fdb9c3 + chatHistoryInteractionId: bc34b41ff5d04e5eb658e0dffc0a3fd8 - request: method: POST uri: http://localhost:3000/api/v1/actions/workspaces/demo_testing/execution/afm/execute body: execution: - attributes: [] - filters: - - positiveAttributeFilter: - in: - values: - - '2024' - label: - identifier: - id: date.year - type: label + attributes: + - label: + identifier: + id: product_name + type: label + localIdentifier: product_name + filters: [] measures: - definition: measure: item: identifier: - id: total_revenue + id: revenue type: metric computeRatio: false filters: [] - localIdentifier: total_revenue + localIdentifier: revenue resultSpec: dimensions: - - itemIdentifiers: [] + - itemIdentifiers: + - product_name localIdentifier: dim_0 - itemIdentifiers: - measureGroup @@ -2003,7 +2000,7 @@ interactions: Cache-Control: - no-cache, no-store, max-age=0, must-revalidate Content-Length: - - '358' + - '646' Content-Type: - application/json DATE: *id001 @@ -2026,7 +2023,7 @@ interactions: X-Frame-Options: - SAMEORIGIN X-Gdc-Cancel-Token: - - 9dc6944c-e0f2-45e6-afc3-0b2276c397e1 + - 00d8589a-ac36-4003-91b7-4d7740c479ca X-GDC-TRACE-ID: *id001 X-Xss-Protection: - 1; mode=block @@ -2034,16 +2031,31 @@ interactions: string: executionResponse: dimensions: - - headers: [] + - headers: + - attributeHeader: + localIdentifier: product_name + label: + id: product_name + type: label + labelName: Product name + attribute: + id: product_name + type: attribute + attributeName: Product name + granularity: null + primaryLabel: + id: product_name + type: label + valueType: TEXT localIdentifier: dim_0 - headers: - measureGroupHeaders: - - localIdentifier: total_revenue + - localIdentifier: revenue format: $#,##0 - name: Total Revenue + name: Revenue localIdentifier: dim_1 links: - executionResult: fb332d669c2540bc879f8591143bc142be634d42:5799a5b2a3489935b1e062ecdac565402623417d73ae07b4fe00c467bbfcb017 + executionResult: 3686f03e3a854572d385962cdf522802010cfa49:8795bd272ad09519a4d36263aad7dc9b1d9ed3cebc1e874adcbd8618d419e005 - request: method: POST uri: http://localhost:3000/api/v1/actions/workspaces/demo_testing/ai/chatHistory @@ -2146,18 +2158,6 @@ interactions: body: string: data: - - id: demo - type: workspace - attributes: - name: Demo - links: - self: http://localhost:3000/api/v1/entities/workspaces/demo - - id: demo_testing - type: workspace - attributes: - name: demo_testing - links: - self: http://localhost:3000/api/v1/entities/workspaces/demo_testing - id: demo_west type: workspace attributes: @@ -2180,6 +2180,18 @@ interactions: type: workspace links: self: http://localhost:3000/api/v1/entities/workspaces/demo_west_california + - id: demo + type: workspace + attributes: + name: Demo + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo + - id: demo_testing + type: workspace + attributes: + name: demo_testing + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo_testing included: - id: demo type: workspace diff --git a/gooddata-sdk/tests/compute/test_compute_service.py b/gooddata-sdk/tests/compute/test_compute_service.py index dd231d57d..a7ce29f53 100644 --- a/gooddata-sdk/tests/compute/test_compute_service.py +++ b/gooddata-sdk/tests/compute/test_compute_service.py @@ -193,7 +193,7 @@ def test_build_exec_def_from_chat_result(test_config): try: _setup_test_workspace(sdk, test_workspace_id, path) - response = sdk.compute.ai_chat(test_workspace_id, "What is the total revenue for the year 2024?") + response = sdk.compute.ai_chat(test_workspace_id, "Display the revenue by product") execution_definition = sdk.compute.build_exec_def_from_chat_result(response) assert execution_definition is not None From 123a41b7260004d64414d6db495390b6bf354ccf Mon Sep 17 00:00:00 2001 From: "Marcelo G. Almiron" Date: Wed, 28 May 2025 15:53:08 +0200 Subject: [PATCH 4/5] feat(ai): Allow to create df from chat response jira: GDAI-238 risk: low --- gooddata-pandas/gooddata_pandas/dataframe.py | 15 + .../dataframe_for_created_visualization.yaml | 2500 +++++++++++++++++ ...est_dataframe_for_created_visualization.py | 60 + gooddata-pandas/tests/gd_test_config.yaml | 1 + 4 files changed, 2576 insertions(+) create mode 100644 gooddata-pandas/tests/dataframe/fixtures/dataframe_for_created_visualization.yaml create mode 100644 gooddata-pandas/tests/dataframe/test_dataframe_for_created_visualization.py diff --git a/gooddata-pandas/gooddata_pandas/dataframe.py b/gooddata-pandas/gooddata_pandas/dataframe.py index 2130a17aa..8045baa92 100644 --- a/gooddata-pandas/gooddata_pandas/dataframe.py +++ b/gooddata-pandas/gooddata_pandas/dataframe.py @@ -183,6 +183,21 @@ def for_visualization(self, visualization_id: str, auto_index: bool = True) -> p return self.for_items(columns, filter_by=filter_by, auto_index=auto_index) + def for_created_visualization( + self, created_visualizations_response: dict + ) -> tuple[pandas.DataFrame, DataFrameMetadata]: + """ + Creates a data frame using a created visualization. + + Args: + created_visualizations_response (dict): Created visualization response. + + Returns: + pandas.DataFrame: A DataFrame instance. + """ + execution_definition = self._sdk.compute.build_exec_def_from_chat_result(created_visualizations_response) + return self.for_exec_def(exec_def=execution_definition) + def result_cache_metadata_for_exec_result_id(self, result_id: str) -> ResultCacheMetadata: """ Retrieves result cache metadata for given :result_id: diff --git a/gooddata-pandas/tests/dataframe/fixtures/dataframe_for_created_visualization.yaml b/gooddata-pandas/tests/dataframe/fixtures/dataframe_for_created_visualization.yaml new file mode 100644 index 000000000..ccc31d0ae --- /dev/null +++ b/gooddata-pandas/tests/dataframe/fixtures/dataframe_for_created_visualization.yaml @@ -0,0 +1,2500 @@ +# (C) 2025 GoodData Corporation +version: 1 +interactions: + - request: + method: GET + uri: http://localhost:3000/api/v1/entities/workspaces/demo_testing?include=workspaces + body: null + headers: + Accept: + - application/vnd.gooddata.api+json + Accept-Encoding: + - br, gzip, deflate + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 404 + message: Not Found + headers: + Cache-Control: + - max-age=5, private + Content-Length: + - '172' + Content-Type: + - application/problem+json + DATE: &id001 + - PLACEHOLDER + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + detail: The requested endpoint does not exist or you do not have permission + to access it. + status: 404 + title: Not Found + traceId: c173d460da8c782d6634327e5ba6671a + - request: + method: GET + uri: http://localhost:3000/api/v1/entities/workspaces/demo_testing?include=workspaces + body: null + headers: + Accept: + - application/vnd.gooddata.api+json + Accept-Encoding: + - br, gzip, deflate + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 404 + message: Not Found + headers: + Cache-Control: + - max-age=5, private + Content-Length: + - '172' + Content-Type: + - application/problem+json + DATE: *id001 + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + detail: The requested endpoint does not exist or you do not have permission + to access it. + status: 404 + title: Not Found + traceId: 57cb93026e7801afa1da2cd2d70409bf + - request: + method: POST + uri: http://localhost:3000/api/v1/entities/workspaces + body: + data: + id: demo_testing + type: workspace + attributes: + name: demo_testing + headers: + Accept: + - application/vnd.gooddata.api+json + Accept-Encoding: + - br, gzip, deflate + Content-Type: + - application/vnd.gooddata.api+json + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 201 + message: Created + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Content-Length: + - '167' + Content-Type: + - application/vnd.gooddata.api+json + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + data: + id: demo_testing + type: workspace + attributes: + name: demo_testing + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo_testing + - request: + method: PUT + uri: http://localhost:3000/api/v1/layout/workspaces/demo_testing/logicalModel + body: + ldm: + datasets: + - grain: + - id: campaign_channel_id + type: attribute + id: campaign_channels + references: + - identifier: + id: campaigns + type: dataset + multivalue: false + sources: + - column: campaign_id + target: + id: campaign_id + type: attribute + dataType: INT + title: Campaign channels + description: Campaign channels + attributes: + - id: campaign_channel_id + labels: [] + sourceColumn: campaign_channel_id + title: Campaign channel id + sourceColumnDataType: STRING + description: Campaign channel id + tags: + - Campaign channels + - id: campaign_channels.category + labels: [] + sourceColumn: category + title: Category + sourceColumnDataType: STRING + description: Category + tags: + - Campaign channels + - id: type + labels: [] + sourceColumn: type + title: Type + sourceColumnDataType: STRING + description: Type + tags: + - Campaign channels + facts: + - id: budget + sourceColumn: budget + title: Budget + sourceColumnDataType: NUMERIC + description: Budget + tags: + - Campaign channels + - id: spend + sourceColumn: spend + title: Spend + sourceColumnDataType: NUMERIC + description: Spend + tags: + - Campaign channels + dataSourceTableId: + dataSourceId: pg_local_docker-demo + id: campaign_channels + type: dataSource + path: + - demo_6d9051d9069a8468 + - campaign_channels + tags: + - Campaign channels + - grain: + - id: campaign_id + type: attribute + id: campaigns + references: [] + title: Campaigns + description: Campaigns + attributes: + - id: campaign_id + labels: [] + sourceColumn: campaign_id + title: Campaign id + sourceColumnDataType: INT + description: Campaign id + tags: + - Campaigns + - id: campaign_name + labels: [] + sourceColumn: campaign_name + title: Campaign name + sourceColumnDataType: STRING + description: Campaign name + tags: + - Campaigns + facts: [] + dataSourceTableId: + dataSourceId: pg_local_docker-demo + id: campaigns + type: dataSource + path: + - demo_6d9051d9069a8468 + - campaigns + tags: + - Campaigns + - grain: + - id: customer_id + type: attribute + id: customers + references: [] + title: Customers + description: Customers + attributes: + - id: customer_id + labels: [] + sourceColumn: customer_id + title: Customer id + sourceColumnDataType: INT + description: Customer id + tags: + - Customers + - id: customer_name + labels: [] + sourceColumn: customer_name + title: Customer name + sourceColumnDataType: STRING + description: Customer name + tags: + - Customers + - id: region + labels: [] + sourceColumn: region + title: Region + sourceColumnDataType: STRING + description: Region + tags: + - Customers + - id: state + labels: + - id: geo__state__location + sourceColumn: geo__state__location + title: Location + sourceColumnDataType: STRING + description: Location + tags: + - Customers + sourceColumn: state + title: State + sourceColumnDataType: STRING + description: State + tags: + - Customers + facts: [] + dataSourceTableId: + dataSourceId: pg_local_docker-demo + id: customers + type: dataSource + path: + - demo_6d9051d9069a8468 + - customers + tags: + - Customers + - grain: + - id: order_line_id + type: attribute + id: order_lines + references: + - identifier: + id: campaigns + type: dataset + multivalue: false + sources: + - column: campaign_id + target: + id: campaign_id + type: attribute + dataType: INT + - identifier: + id: customers + type: dataset + multivalue: false + sources: + - column: customer_id + target: + id: customer_id + type: attribute + dataType: INT + - identifier: + id: date + type: dataset + multivalue: false + sources: + - column: date + target: + id: date + type: date + dataType: DATE + - identifier: + id: products + type: dataset + multivalue: false + sources: + - column: product_id + target: + id: product_id + type: attribute + dataType: INT + title: Order lines + description: Order lines + attributes: + - id: order_id + labels: [] + sourceColumn: order_id + title: Order id + sourceColumnDataType: STRING + description: Order id + tags: + - Order lines + - id: order_line_id + labels: [] + sourceColumn: order_line_id + title: Order line id + sourceColumnDataType: STRING + description: Order line id + tags: + - Order lines + - id: order_status + labels: [] + sourceColumn: order_status + title: Order status + sourceColumnDataType: STRING + description: Order status + tags: + - Order lines + facts: + - id: price + sourceColumn: price + title: Price + sourceColumnDataType: NUMERIC + description: Price + tags: + - Order lines + - id: quantity + sourceColumn: quantity + title: Quantity + sourceColumnDataType: NUMERIC + description: Quantity + tags: + - Order lines + dataSourceTableId: + dataSourceId: pg_local_docker-demo + id: order_lines + type: dataSource + path: + - demo_6d9051d9069a8468 + - order_lines + tags: + - Order lines + workspaceDataFilterColumns: + - dataType: STRING + name: wdf__region + - dataType: STRING + name: wdf__state + - grain: + - id: product_id + type: attribute + id: products + references: [] + title: Products + description: Products + attributes: + - id: product_id + labels: [] + sourceColumn: product_id + title: Product id + sourceColumnDataType: INT + description: Product id + tags: + - Products + - id: product_name + labels: [] + sourceColumn: product_name + title: Product name + sourceColumnDataType: STRING + description: Product name + tags: + - Products + - id: products.category + labels: [] + sourceColumn: category + title: Category + sourceColumnDataType: STRING + description: Category + tags: + - Products + facts: [] + dataSourceTableId: + dataSourceId: pg_local_docker-demo + id: products + type: dataSource + path: + - demo_6d9051d9069a8468 + - products + tags: + - Products + dateInstances: + - granularities: + - DAY + - WEEK + - MONTH + - QUARTER + - YEAR + granularitiesFormatting: + titleBase: '' + titlePattern: '%titleBase - %granularityTitle' + id: date + title: Date + description: '' + tags: + - Date + headers: + Accept-Encoding: + - br, gzip, deflate + Content-Type: + - application/json + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 204 + message: No Content + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: '' + - request: + method: PUT + uri: http://localhost:3000/api/v1/layout/workspaces/demo_testing/analyticsModel + body: + analytics: + analyticalDashboards: + - content: + filterContextRef: + identifier: + id: 4717b786-2c2e-4596-adb5-4f8b0ab0e19a + type: filterContext + layout: + sections: + - header: + description: All in one description + title: All in one title + items: + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: top_10_customers + type: visualizationObject + localIdentifier: 2c7400ac-5f63-46f8-aa12-a2debe13fd14 + properties: {} + title: Top 10 Customers + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: revenue_by_product + type: visualizationObject + localIdentifier: a50daab7-fb78-45eb-a2b4-d5cc8cbd89e9 + properties: {} + title: Revenue by Product + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: revenue_by_category_trend + type: visualizationObject + localIdentifier: efccc783-5896-4eb6-890f-2e51ece3f159 + properties: {} + title: Revenue by Category Trend + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: product_saleability + type: visualizationObject + localIdentifier: d738d85f-e935-4e2c-b8b4-a8b456f55079 + properties: {} + title: Product Saleability + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: product_categories_pie_chart + type: visualizationObject + localIdentifier: 8c194c85-bad6-42da-b4e3-08d270278316 + properties: {} + title: Product Categories Pie Chart + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: percentage_of_customers_by_region + type: visualizationObject + localIdentifier: 2c3307b2-581f-4bab-9252-6b5279565b24 + properties: {} + title: Percentage of Customers by Region + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: customers_trend + type: visualizationObject + localIdentifier: 87505bb0-d954-4add-811d-f4e75e431660 + properties: {} + title: Customers Trend + type: insight + - size: + xl: + gridWidth: 6 + type: IDashboardLayoutItem + widget: + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: campaign_spend + type: visualizationObject + localIdentifier: 0cb01f6a-6ea6-4c22-bb12-ded00a9eac66 + properties: {} + title: Campaign Spend + type: insight + - size: + xl: + gridWidth: 12 + type: IDashboardLayoutItem + widget: + dateDataSet: + identifier: + id: date + type: dataset + description: '' + drills: [] + ignoreDashboardFilters: [] + insight: + identifier: + id: percent_revenue_per_product_by_customer_and_category + type: visualizationObject + localIdentifier: 2213d6e4-6df7-458e-806d-f02bae5ce66a + properties: {} + title: '% Revenue per Product by Customer and Category' + type: insight + type: IDashboardLayoutSection + type: IDashboardLayout + version: '2' + id: b2f2d436-9831-4fe0-81df-8c59fd33242b + title: All visualizations 1 with custom filter + description: '' + analyticalDashboardExtensions: [] + attributeHierarchies: [] + dashboardPlugins: [] + filterContexts: + - content: + filters: + - attributeFilter: + attributeElements: + uris: + - Biolid + - ChalkTalk + - Compglass + - Elentrix + displayForm: + identifier: + id: product_name + type: label + filterElementsBy: [] + localIdentifier: 6b94bbb585d44c79967867719e524fae + negativeSelection: false + selectionMode: multi + version: '2' + id: 4717b786-2c2e-4596-adb5-4f8b0ab0e19a + title: filterContext + description: '' + - content: + filters: + - dateFilter: + from: '0' + granularity: GDC.time.year + to: '0' + type: relative + version: '2' + id: 9f2b1f37-befa-450e-a6cc-dc576845c412 + title: filterContext + description: '' + metrics: + - content: + format: '#,##0' + maql: SELECT COUNT({attribute/customer_id},{attribute/order_line_id}) + id: amount_of_active_customers + title: '# of Active Customers' + description: '' + - content: + format: '#,##0' + maql: SELECT COUNT({attribute/order_id}) + id: amount_of_orders + title: '# of Orders' + description: '' + - content: + format: '#,##0' + maql: 'SELECT {metric/amount_of_active_customers} WHERE (SELECT {metric/revenue} + BY {attribute/customer_id}) > 10000 ' + id: amount_of_top_customers + title: '# of Top Customers' + description: '' + - content: + format: '#,##0.00' + maql: SELECT {metric/amount_of_orders} WHERE NOT ({label/order_status} + IN ("null", "Returned", "Canceled")) + id: amount_of_valid_orders + title: '# of Valid Orders' + description: '' + - content: + format: $#,##0 + maql: SELECT SUM({fact/spend}) + id: campaign_spend + title: Campaign Spend + description: '' + - content: + format: $#,##0 + maql: SELECT SUM({fact/price}*{fact/quantity}) + id: order_amount + title: Order Amount + description: '' + - content: + format: '#,##0.0%' + maql: SELECT {metric/revenue} / {metric/total_revenue} + id: percent_revenue + title: '% Revenue' + description: '' + - content: + format: '#,##0.0%' + maql: "SELECT\n (SELECT {metric/revenue} WHERE (SELECT {metric/revenue_top_10}\ + \ BY {attribute/customer_id}) > 0)\n /\n {metric/revenue}" + id: percent_revenue_from_top_10_customers + title: '% Revenue from Top 10 Customers' + description: '' + - content: + format: '#,##0.0%' + maql: "SELECT\n (SELECT {metric/revenue} WHERE (SELECT {metric/revenue_top_10_percent}\ + \ BY {attribute/customer_id}) > 0)\n /\n {metric/revenue}" + id: percent_revenue_from_top_10_percent_customers + title: '% Revenue from Top 10% Customers' + description: '' + - content: + format: '#,##0.0%' + maql: "SELECT\n (SELECT {metric/revenue} WHERE (SELECT {metric/revenue_top_10_percent}\ + \ BY {attribute/product_id}) > 0)\n /\n {metric/revenue}" + id: percent_revenue_from_top_10_percent_products + title: '% Revenue from Top 10% Products' + description: '' + - content: + format: '#,##0.0%' + maql: "SELECT\n (SELECT {metric/revenue} WHERE (SELECT {metric/revenue_top_10}\ + \ BY {attribute/product_id}) > 0)\n /\n {metric/revenue}" + id: percent_revenue_from_top_10_products + title: '% Revenue from Top 10 Products' + description: '' + - content: + format: '#,##0.0%' + maql: SELECT {metric/revenue} / (SELECT {metric/revenue} BY {attribute/products.category}, + ALL OTHER) + id: percent_revenue_in_category + title: '% Revenue in Category' + description: '' + - content: + format: '#,##0.0%' + maql: SELECT {metric/revenue} / (SELECT {metric/revenue} BY ALL {attribute/product_id}) + id: percent_revenue_per_product + title: '% Revenue per Product' + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/order_amount} WHERE NOT ({label/order_status} + IN ("null", "Returned", "Canceled")) + id: revenue + title: Revenue + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE {label/products.category} IN ("Clothing") + id: revenue-clothing + title: Revenue (Clothing) + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE {label/products.category} IN ( + "Electronics") + id: revenue-electronic + title: Revenue (Electronic) + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE {label/products.category} IN ("Home") + id: revenue-home + title: Revenue (Home) + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE {label/products.category} IN ("Outdoor") + id: revenue-outdoor + title: Revenue (Outdoor) + description: '' + - content: + format: $#,##0.0 + maql: SELECT AVG(SELECT {metric/revenue} BY {attribute/customer_id}) + id: revenue_per_customer + title: Revenue per Customer + description: '' + - content: + format: $#,##0.0 + maql: SELECT {metric/revenue} / {metric/campaign_spend} + id: revenue_per_dollar_spent + title: Revenue per Dollar Spent + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE TOP(10) OF ({metric/revenue}) + id: revenue_top_10 + title: Revenue / Top 10 + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/revenue} WHERE TOP(10%) OF ({metric/revenue}) + id: revenue_top_10_percent + title: Revenue / Top 10% + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/revenue} BY ALL OTHER + id: total_revenue + title: Total Revenue + description: '' + - content: + format: $#,##0 + maql: SELECT {metric/total_revenue} WITHOUT PARENT FILTER + id: total_revenue-no_filters + title: Total Revenue (No Filters) + description: '' + visualizationObjects: + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: campaign_spend + type: metric + localIdentifier: d319bcb2d8c04442a684e3b3cd063381 + title: Campaign Spend + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: campaign_channels.category + type: label + localIdentifier: 291c085e7df8420db84117ca49f59c49 + localIdentifier: view + - items: + - attribute: + displayForm: + identifier: + id: campaign_name + type: label + localIdentifier: d9dd143d647d4d148405a60ec2cf59bc + localIdentifier: segment + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: type + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: campaign_channels.category + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: campaign_name + type: label + notIn: + values: [] + properties: + controls: + legend: + position: bottom + version: '2' + visualizationUrl: local:treemap + id: campaign_spend + title: Campaign Spend + description: '' + - content: + buckets: + - items: + - measure: + alias: Active Customers + definition: + measureDefinition: + computeRatio: false + filters: [] + item: + identifier: + id: amount_of_active_customers + type: metric + localIdentifier: 2ba0b87b59ca41a4b1530e81a5c1d081 + title: '# of Active Customers' + localIdentifier: measures + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue_per_customer + type: metric + localIdentifier: ec0606894b9f4897b7beaf1550608928 + title: Revenue per Customer + localIdentifier: secondary_measures + - items: + - attribute: + displayForm: + identifier: + id: date.month + type: label + localIdentifier: 0de7d7f08af7480aa636857a26be72b6 + localIdentifier: view + filters: + - relativeDateFilter: + dataSet: + identifier: + id: date + type: dataset + from: -11 + granularity: GDC.time.month + to: 0 + properties: + controls: + colorMapping: + - color: + type: guid + value: '20' + id: 2ba0b87b59ca41a4b1530e81a5c1d081 + - color: + type: guid + value: '4' + id: ec0606894b9f4897b7beaf1550608928 + dualAxis: true + legend: + position: bottom + primaryChartType: column + secondaryChartType: line + secondary_yaxis: + measures: + - ec0606894b9f4897b7beaf1550608928 + xaxis: + name: + visible: false + rotation: auto + version: '2' + visualizationUrl: local:combo2 + id: customers_trend + title: Customers Trend + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: percent_revenue_per_product + type: metric + localIdentifier: 08d8346c1ce7438994b251991c0fbf65 + title: '% Revenue per Product' + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: b2350c06688b4da9b3833ebcce65527f + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: customer_name + type: label + localIdentifier: 7a4045fd00ac44579f52406df679435f + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: 6a003ffd14994237ba64c4a02c488429 + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: 75ea396d0c8b48098e31dccf8b5801d3 + localIdentifier: attribute + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: customer_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + properties: + sortItems: + - attributeSortItem: + attributeIdentifier: 7a4045fd00ac44579f52406df679435f + direction: asc + version: '2' + visualizationUrl: local:table + id: percent_revenue_per_product_by_customer_and_category + title: '% Revenue per Product by Customer and Category' + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: amount_of_active_customers + type: metric + localIdentifier: 1a14cdc1293c46e89a2e25d3e741d235 + title: '# of Active Customers' + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: date.month + type: label + localIdentifier: c1feca1864244ec2ace7a9b9d7fda231 + localIdentifier: view + - items: + - attribute: + displayForm: + identifier: + id: region + type: label + localIdentifier: 530cddbd7ca04d039e73462d81ed44d5 + localIdentifier: stack + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: region + type: label + notIn: + values: [] + - relativeDateFilter: + dataSet: + identifier: + id: date + type: dataset + from: -11 + granularity: GDC.time.month + to: 0 + properties: + controls: + legend: + position: bottom + stackMeasuresToPercent: true + version: '2' + visualizationUrl: local:area + id: percentage_of_customers_by_region + title: Percentage of Customers by Region + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 590d332ef686468b8878ae41b23341c6 + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: b166c71091864312a14c7ae8ff886ffe + localIdentifier: view + - items: + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: e920a50e0bbb49788df0aac53634c1cd + localIdentifier: segment + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + properties: + controls: + legend: + position: bottom + version: '2' + visualizationUrl: local:treemap + id: product_breakdown + title: Product Breakdown + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + computeRatio: true + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 162b857af49d45769bc12604a5c192b9 + title: '% Revenue' + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: fe513cef1c6244a5ac21c5f49c56b108 + localIdentifier: view + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + properties: + controls: + dataLabels: + visible: auto + legend: + position: bottom + version: '2' + visualizationUrl: local:donut + id: product_categories_pie_chart + title: Product Categories Pie Chart + description: '' + - content: + buckets: + - items: + - measure: + alias: Previous Period + definition: + popMeasureDefinition: + measureIdentifier: c82e025fa2db4afea9a600a424591dbe + popAttribute: + identifier: + id: date.year + type: label + localIdentifier: c82e025fa2db4afea9a600a424591dbe_pop + - measure: + alias: This Period + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: c82e025fa2db4afea9a600a424591dbe + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: c804ef5ba7944a5a9f360c86a9e95e9a + localIdentifier: view + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + - relativeDateFilter: + dataSet: + identifier: + id: date + type: dataset + from: -11 + granularity: GDC.time.month + to: 0 + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + properties: + controls: + legend: + position: bottom + stackMeasures: false + xaxis: + name: + visible: false + yaxis: + name: + visible: false + version: '2' + visualizationUrl: local:column + id: product_revenue_comparison-over_previous_period + title: Product Revenue Comparison (over previous period) + description: '' + - content: + buckets: + - items: + - measure: + alias: Number of Orders + definition: + measureDefinition: + filters: [] + item: + identifier: + id: amount_of_orders + type: metric + localIdentifier: aeb5d51a162d4b59aba3bd6ddebcc780 + title: '# of Orders' + localIdentifier: measures + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 94b3edd3a73c4a48a4d13bbe9442cc98 + title: Revenue + localIdentifier: secondary_measures + - items: + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: d2a991bdd123448eb2be73d79f1180c4 + localIdentifier: attribute + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + properties: + controls: + dataLabels: + visible: auto + grid: + enabled: true + version: '2' + visualizationUrl: local:scatter + id: product_saleability + title: Product Saleability + description: '' + - content: + buckets: + - items: + - measure: + alias: Items Sold + definition: + measureDefinition: + aggregation: sum + filters: [] + item: + identifier: + id: quantity + type: fact + format: '#,##0.00' + localIdentifier: 29486504dd0e4a36a18b0b2f792d3a46 + title: Sum of Quantity + - measure: + definition: + measureDefinition: + aggregation: avg + filters: [] + item: + identifier: + id: price + type: fact + format: '#,##0.00' + localIdentifier: aa6391acccf1452f8011201aef9af492 + title: Avg Price + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: percent_revenue_in_category + type: metric + localIdentifier: 2cd39539d8da46c9883e63caa3ba7cc0 + title: '% Revenue in Category' + - measure: + alias: Total Revenue + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 9a0f08331c094c7facf2a0b4f418de0a + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: 06bc6b3b9949466494e4f594c11f1bff + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: 192668bfb6a74e9ab7b5d1ce7cb68ea3 + localIdentifier: attribute + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: customer_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + properties: + sortItems: + - attributeSortItem: + attributeIdentifier: 06bc6b3b9949466494e4f594c11f1bff + direction: asc + version: '2' + visualizationUrl: local:table + id: revenue_and_quantity_by_product_and_category + title: Revenue and Quantity by Product and Category + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 7df6c34387744d69b23ec92e1a5cf543 + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: date.month + type: label + localIdentifier: 4bb4fc1986c546de9ad976e6ec23fed4 + localIdentifier: trend + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: 34bddcb1cd024902a82396216b0fa9d8 + localIdentifier: segment + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + - relativeDateFilter: + dataSet: + identifier: + id: date + type: dataset + granularity: GDC.time.year + properties: + controls: + legend: + position: bottom + version: '2' + visualizationUrl: local:line + id: revenue_by_category_trend + title: Revenue by Category Trend + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 4ae3401bdbba4938afe983df4ba04e1c + title: Revenue + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: 1c8ba72dbfc84ddd913bf81dc355c427 + localIdentifier: view + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + properties: {} + version: '2' + visualizationUrl: local:bar + id: revenue_by_product + title: Revenue by Product + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: campaign_spend + type: metric + localIdentifier: 13a50d811e474ac6808d8da7f4673b35 + title: Campaign Spend + localIdentifier: measures + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue_per_dollar_spent + type: metric + localIdentifier: a0f15e82e6334280a44dbedc7d086e7c + title: Revenue per Dollar Spent + localIdentifier: secondary_measures + - items: + - attribute: + displayForm: + identifier: + id: campaign_name + type: label + localIdentifier: 1d9fa968bafb423eb29c938dfb1207ff + localIdentifier: attribute + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: campaign_name + type: label + notIn: + values: [] + properties: + controls: + xaxis: + min: '0' + yaxis: + min: '0' + version: '2' + visualizationUrl: local:scatter + id: revenue_per_usd_vs_spend_by_campaign + title: Revenue per $ vs Spend by Campaign + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + computeRatio: false + filters: [] + item: + identifier: + id: revenue + type: metric + localIdentifier: 60c854969a9c4c278ab596d99c222e92 + title: Revenue + localIdentifier: measures + - items: + - measure: + alias: Number of Orders + definition: + measureDefinition: + computeRatio: false + filters: [] + item: + identifier: + id: amount_of_orders + type: metric + localIdentifier: c2fa7ef48cc54af99f8c280eb451e051 + title: '# of Orders' + localIdentifier: secondary_measures + - items: + - attribute: + displayForm: + identifier: + id: date.month + type: label + localIdentifier: 413ac374b65648fa96826ca01d47bdda + localIdentifier: view + filters: + - relativeDateFilter: + dataSet: + identifier: + id: date + type: dataset + from: -3 + granularity: GDC.time.quarter + to: 0 + properties: + controls: + dualAxis: true + legend: + position: bottom + primaryChartType: column + secondaryChartType: line + secondary_yaxis: + measures: + - c2fa7ef48cc54af99f8c280eb451e051 + xaxis: + name: + visible: false + rotation: auto + version: '2' + visualizationUrl: local:combo2 + id: revenue_trend + title: Revenue Trend + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue_top_10 + type: metric + localIdentifier: 3f127ccfe57a40399e23f9ae2a4ad810 + title: Revenue / Top 10 + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: customer_name + type: label + localIdentifier: f4e39e24f11e4827a191c30d65c89d2c + localIdentifier: view + - items: + - attribute: + displayForm: + identifier: + id: state + type: label + localIdentifier: bbccd430176d428caed54c99afc9589e + localIdentifier: stack + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: customer_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: state + type: label + notIn: + values: [] + properties: + controls: + legend: + position: bottom + version: '2' + visualizationUrl: local:bar + id: top_10_customers + title: Top 10 Customers + description: '' + - content: + buckets: + - items: + - measure: + definition: + measureDefinition: + filters: [] + item: + identifier: + id: revenue_top_10 + type: metric + localIdentifier: 77dc71bbac92412bac5f94284a5919df + title: Revenue / Top 10 + localIdentifier: measures + - items: + - attribute: + displayForm: + identifier: + id: product_name + type: label + localIdentifier: 781952e728204dcf923142910cc22ae2 + localIdentifier: view + - items: + - attribute: + displayForm: + identifier: + id: products.category + type: label + localIdentifier: fe513cef1c6244a5ac21c5f49c56b108 + localIdentifier: stack + filters: + - negativeAttributeFilter: + displayForm: + identifier: + id: product_name + type: label + notIn: + values: [] + - negativeAttributeFilter: + displayForm: + identifier: + id: products.category + type: label + notIn: + values: [] + properties: + controls: + legend: + position: bottom + version: '2' + visualizationUrl: local:bar + id: top_10_products + title: Top 10 Products + description: '' + exportDefinitions: [] + headers: + Accept-Encoding: + - br, gzip, deflate + Content-Type: + - application/json + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 204 + message: No Content + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: '' + - request: + method: POST + uri: http://localhost:3000/api/v1/actions/workspaces/demo_testing/ai/chat + body: + question: Display the revenue by product + headers: + Accept: + - application/json + Accept-Encoding: + - br, gzip, deflate + Content-Type: + - application/json + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Content-Length: + - '775' + Content-Type: + - application/json + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + routing: + useCase: CREATE_VISUALIZATION + reasoning: Creating a new visualization ... + createdVisualizations: + objects: + - id: revenue_by_product + title: Revenue by Product + visualizationType: COLUMN + metrics: + - id: revenue + type: metric + title: Revenue + dimensionality: + - id: product_name + type: attribute + title: Product name + filters: [] + suggestions: + - query: Slice by 'Category' + label: Slice by Category + - query: Switch to a table view for detailed comparison + label: Switch to Table View + reasoning: ' + + + + + + Here is a column chart showing the Revenue by Product grouped by Product + name. + + - Metrics: Revenue + + - Attributes: Product name + + - Filter: None + + + ' + chatHistoryInteractionId: fac7be82923f471782272343ad1a6ad1 + - request: + method: POST + uri: http://localhost:3000/api/v1/actions/workspaces/demo_testing/execution/afm/execute + body: + execution: + attributes: + - label: + identifier: + id: product_name + type: label + localIdentifier: product_name + filters: [] + measures: + - definition: + measure: + item: + identifier: + id: revenue + type: metric + computeRatio: false + filters: [] + localIdentifier: revenue + resultSpec: + dimensions: + - itemIdentifiers: + - product_name + localIdentifier: dim_0 + - itemIdentifiers: + - measureGroup + localIdentifier: dim_1 + headers: + Accept: + - application/json + Accept-Encoding: + - br, gzip, deflate + Content-Type: + - application/json + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Content-Length: + - '646' + Content-Type: + - application/json + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-Gdc-Cancel-Token: + - 66150d36-9a7f-4494-b342-8be4c10bceac + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + executionResponse: + dimensions: + - headers: + - attributeHeader: + localIdentifier: product_name + label: + id: product_name + type: label + labelName: Product name + attribute: + id: product_name + type: attribute + attributeName: Product name + granularity: null + primaryLabel: + id: product_name + type: label + valueType: TEXT + localIdentifier: dim_0 + - headers: + - measureGroupHeaders: + - localIdentifier: revenue + format: $#,##0 + name: Revenue + localIdentifier: dim_1 + links: + executionResult: 3686f03e3a854572d385962cdf522802010cfa49:8795bd272ad09519a4d36263aad7dc9b1d9ed3cebc1e874adcbd8618d419e005 + - request: + method: GET + uri: http://localhost:3000/api/v1/actions/workspaces/demo_testing/execution/afm/execute/result/3686f03e3a854572d385962cdf522802010cfa49%3A8795bd272ad09519a4d36263aad7dc9b1d9ed3cebc1e874adcbd8618d419e005/metadata + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - br, gzip, deflate + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Content-Length: + - '1186' + Content-Type: + - application/json + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + afm: + attributes: + - localIdentifier: product_name + label: + identifier: + id: product_name + type: label + showAllValues: false + filters: [] + measures: + - localIdentifier: revenue + definition: + measure: + item: + identifier: + id: revenue + type: metric + computeRatio: false + filters: [] + auxMeasures: [] + executionResponse: + dimensions: + - headers: + - attributeHeader: + localIdentifier: product_name + label: + id: product_name + type: label + labelName: Product name + attribute: + id: product_name + type: attribute + attributeName: Product name + granularity: null + primaryLabel: + id: product_name + type: label + valueType: TEXT + localIdentifier: dim_0 + - headers: + - measureGroupHeaders: + - localIdentifier: revenue + format: $#,##0 + name: Revenue + localIdentifier: dim_1 + links: + executionResult: 3686f03e3a854572d385962cdf522802010cfa49:8795bd272ad09519a4d36263aad7dc9b1d9ed3cebc1e874adcbd8618d419e005 + resultSpec: + dimensions: + - localIdentifier: dim_0 + itemIdentifiers: + - product_name + sorting: [] + - localIdentifier: dim_1 + itemIdentifiers: + - measureGroup + sorting: [] + totals: [] + resultSize: 364 + - request: + method: GET + uri: http://localhost:3000/api/v1/actions/workspaces/demo_testing/execution/afm/execute/result/3686f03e3a854572d385962cdf522802010cfa49%3A8795bd272ad09519a4d36263aad7dc9b1d9ed3cebc1e874adcbd8618d419e005?offset=0%2C0&limit=100%2C100 + body: null + headers: + Accept: + - application/json + Accept-Encoding: + - br, gzip, deflate + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Content-Length: + - '1797' + Content-Type: + - application/json + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + data: + - - 4725.73 + - - 14421.37 + - - 34697.71 + - - 17657.35 + - - 12995.87 + - - 27662.09 + - - 47766.74 + - - 44026.52 + - - 99440.44 + - - 40307.76 + - - 6408.91 + - - 16744.48 + - - 18841.17 + - - 7386.15 + - - 17431.11 + - - 16494.89 + - - 18469.15 + - - 17937.49 + dimensionHeaders: + - headerGroups: + - headers: + - attributeHeader: + labelValue: Applica + primaryLabelValue: Applica + - attributeHeader: + labelValue: Artego + primaryLabelValue: Artego + - attributeHeader: + labelValue: Biolid + primaryLabelValue: Biolid + - attributeHeader: + labelValue: ChalkTalk + primaryLabelValue: ChalkTalk + - attributeHeader: + labelValue: Compglass + primaryLabelValue: Compglass + - attributeHeader: + labelValue: Elentrix + primaryLabelValue: Elentrix + - attributeHeader: + labelValue: Integres + primaryLabelValue: Integres + - attributeHeader: + labelValue: Magnemo + primaryLabelValue: Magnemo + - attributeHeader: + labelValue: Neptide + primaryLabelValue: Neptide + - attributeHeader: + labelValue: Optique + primaryLabelValue: Optique + - attributeHeader: + labelValue: Peril + primaryLabelValue: Peril + - attributeHeader: + labelValue: Polo Shirt + primaryLabelValue: Polo Shirt + - attributeHeader: + labelValue: PortaCode + primaryLabelValue: PortaCode + - attributeHeader: + labelValue: Pullover + primaryLabelValue: Pullover + - attributeHeader: + labelValue: Shorts + primaryLabelValue: Shorts + - attributeHeader: + labelValue: Skirt + primaryLabelValue: Skirt + - attributeHeader: + labelValue: Slacks + primaryLabelValue: Slacks + - attributeHeader: + labelValue: T-Shirt + primaryLabelValue: T-Shirt + - headerGroups: + - headers: + - measureHeader: + measureIndex: 0 + grandTotals: [] + paging: + count: + - 18 + - 1 + offset: + - 0 + - 0 + total: + - 18 + - 1 + metadata: + dataSourceMessages: [] + - request: + method: POST + uri: http://localhost:3000/api/v1/actions/workspaces/demo_testing/ai/chatHistory + body: + reset: true + headers: + Accept: + - application/json + Accept-Encoding: + - br, gzip, deflate + Content-Type: + - application/json + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Content-Length: + - '51' + Content-Type: + - application/json + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + interactions: [] + threadId: demo_testing.admin + - request: + method: GET + uri: http://localhost:3000/api/v1/entities/workspaces?include=workspaces&page=0&size=500 + body: null + headers: + Accept: + - application/vnd.gooddata.api+json + Accept-Encoding: + - br, gzip, deflate + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 200 + message: OK + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + Content-Length: + - '1274' + Content-Type: + - application/vnd.gooddata.api+json + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: + data: + - id: demo_west + type: workspace + attributes: + name: Demo West + relationships: + parent: + data: + id: demo + type: workspace + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo_west + - id: demo_west_california + type: workspace + attributes: + name: Demo West California + relationships: + parent: + data: + id: demo_west + type: workspace + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo_west_california + - id: demo + type: workspace + attributes: + name: Demo + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo + - id: demo_testing + type: workspace + attributes: + name: demo_testing + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo_testing + included: + - id: demo + type: workspace + attributes: + name: Demo + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo + - id: demo_west + type: workspace + attributes: + name: Demo West + links: + self: http://localhost:3000/api/v1/entities/workspaces/demo_west + links: + self: http://localhost:3000/api/v1/entities/workspaces?include=workspaces&page=0&size=500 + next: http://localhost:3000/api/v1/entities/workspaces?include=workspaces&page=1&size=500 + - request: + method: DELETE + uri: http://localhost:3000/api/v1/entities/workspaces/demo_testing + body: null + headers: + Accept-Encoding: + - br, gzip, deflate + X-GDC-VALIDATE-RELATIONS: + - 'true' + X-Requested-With: + - XMLHttpRequest + response: + status: + code: 204 + message: No Content + headers: + Cache-Control: + - no-cache, no-store, max-age=0, must-revalidate + DATE: *id001 + Expires: + - '0' + Featurepolicy: + - geolocation 'none'; midi 'none'; notifications 'none'; push 'none'; sync-xhr + 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope + 'none'; speaker 'none'; vibrate 'none'; fullscreen 'none'; payment 'none'; + Pragma: + - no-cache + Referrer-Policy: + - same-origin + Vary: + - Origin + - Access-Control-Request-Method + - Access-Control-Request-Headers + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - SAMEORIGIN + X-GDC-TRACE-ID: *id001 + X-Xss-Protection: + - 1; mode=block + body: + string: '' diff --git a/gooddata-pandas/tests/dataframe/test_dataframe_for_created_visualization.py b/gooddata-pandas/tests/dataframe/test_dataframe_for_created_visualization.py new file mode 100644 index 000000000..511865985 --- /dev/null +++ b/gooddata-pandas/tests/dataframe/test_dataframe_for_created_visualization.py @@ -0,0 +1,60 @@ +# (C) 2025 GoodData Corporation +from pathlib import Path + +from gooddata_pandas import DataFrameFactory +from gooddata_sdk import CatalogWorkspace +from gooddata_sdk.sdk import GoodDataSdk +from tests_support.vcrpy_utils import get_vcr + +gd_vcr = get_vcr() + +_current_dir = Path(__file__).parent.absolute() +_fixtures_dir = _current_dir / "fixtures" + + +def _setup_test_workspace(sdk: GoodDataSdk, test_workspace_id: str, path: Path) -> None: + """Helper function to set up test workspace with required models. + + Args: + sdk: GoodData SDK instance + test_workspace_id: ID of the test workspace + path: Path to the directory containing model files + """ + # Check if workspace already exists + try: + sdk.catalog_workspace.get_workspace(test_workspace_id) + except Exception: + workspace = CatalogWorkspace(workspace_id=test_workspace_id, name=test_workspace_id) + sdk.catalog_workspace.create_or_update(workspace) + + # Load LDM from disk and put it to the workspace + ldm_from_disk = sdk.catalog_workspace_content.load_ldm_from_disk(path) + sdk.catalog_workspace_content.put_declarative_ldm(test_workspace_id, ldm_from_disk, standalone_copy=True) + + # Load Analytics Model from disk and put it to the workspace + am_from_disk = sdk.catalog_workspace_content.load_analytics_model_from_disk(path) + sdk.catalog_workspace_content.put_declarative_analytics_model(test_workspace_id, am_from_disk) + + +@gd_vcr.use_cassette(str(_fixtures_dir / "dataframe_for_created_visualization.yaml")) +def test_dataframe_for_created_visualization(test_config): + # Get SDK instance and create test workspace + sdk = GoodDataSdk.create(host_=test_config["host"], token_=test_config["token"]) + gdf = DataFrameFactory(sdk, test_config["workspace_test"]) + path = _current_dir / "load" / "ai" + test_workspace_id = test_config["workspace_test"] + + try: + _setup_test_workspace(sdk, test_workspace_id, path) + response = sdk.compute.ai_chat(test_workspace_id, "Display the revenue by product") + + df, df_metadata = gdf.for_created_visualization(response) + + assert len(df.columns) == 1 + assert len(df) == 18 + assert df.columns[0] == ("Revenue",) + assert df.index.names[0] == "Product name" + + finally: + sdk.compute.reset_ai_chat_history(test_workspace_id) + sdk.catalog_workspace.delete_workspace(test_workspace_id) diff --git a/gooddata-pandas/tests/gd_test_config.yaml b/gooddata-pandas/tests/gd_test_config.yaml index 92814e219..9cf73b755 100644 --- a/gooddata-pandas/tests/gd_test_config.yaml +++ b/gooddata-pandas/tests/gd_test_config.yaml @@ -2,4 +2,5 @@ host: "http://localhost:3000" token: "YWRtaW46Ym9vdHN0cmFwOmFkbWluMTIz" workspace: "demo" +workspace_test: "demo_testing" header_host: localhost From 48f2bfdad6b28b0db02b19a419d05f9dafab9949 Mon Sep 17 00:00:00 2001 From: "Marcelo G. Almiron" Date: Wed, 28 May 2025 17:29:59 +0200 Subject: [PATCH 5/5] style: Use default values for missing key in dict jira: GDAI-238 risk: low --- .../dataframe/test_dataframe_for_created_visualization.py | 4 ++++ gooddata-sdk/gooddata_sdk/compute/service.py | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/gooddata-pandas/tests/dataframe/test_dataframe_for_created_visualization.py b/gooddata-pandas/tests/dataframe/test_dataframe_for_created_visualization.py index 511865985..121281525 100644 --- a/gooddata-pandas/tests/dataframe/test_dataframe_for_created_visualization.py +++ b/gooddata-pandas/tests/dataframe/test_dataframe_for_created_visualization.py @@ -38,6 +38,10 @@ def _setup_test_workspace(sdk: GoodDataSdk, test_workspace_id: str, path: Path) @gd_vcr.use_cassette(str(_fixtures_dir / "dataframe_for_created_visualization.yaml")) def test_dataframe_for_created_visualization(test_config): + # To recreate the cassette, a complete local GoodData environment with gen_ai service is required. + # The gen_ai service cannot be included in the already available single docker image due to size constraints. + # Since in such cases we are interacting with an LLM, the results are not 100% deterministic. + # Get SDK instance and create test workspace sdk = GoodDataSdk.create(host_=test_config["host"], token_=test_config["token"]) gdf = DataFrameFactory(sdk, test_config["workspace_test"]) diff --git a/gooddata-sdk/gooddata_sdk/compute/service.py b/gooddata-sdk/gooddata_sdk/compute/service.py index 5ada0a5c9..ba49759b7 100644 --- a/gooddata-sdk/gooddata_sdk/compute/service.py +++ b/gooddata-sdk/gooddata_sdk/compute/service.py @@ -100,9 +100,9 @@ def build_exec_def_from_chat_result(self, chat_result: ChatResult) -> ExecutionD ExecutionDefinition: Execution definition built from chat result visualization """ vis_object = chat_result.created_visualizations["objects"][0] - metrics_def = vis_object.get("metrics") or [] - filters_def = vis_object.get("filters") or [] - dimensionality_def = vis_object.get("dimensionality") or [] + metrics_def = vis_object.get("metrics", []) + filters_def = vis_object.get("filters", []) + dimensionality_def = vis_object.get("dimensionality", []) metrics = [VisualizationToSdkConverter.convert_metric(m) for m in metrics_def] filters = [VisualizationToSdkConverter.convert_filter(f) for f in filters_def]