From b6c10ecf2121d89650e5eb71704bb8ab90c9c24e Mon Sep 17 00:00:00 2001 From: Dmitry Dementev Date: Tue, 8 Sep 2026 03:17:00 -0400 Subject: [PATCH] =?UTF-8?q?feat(superset):=20=D0=BF=D0=BE=D0=B4=D0=B0?= =?UTF-8?q?=D1=87=D0=B0=20=D0=B4=D0=B0=D1=88=D0=B1=D0=BE=D1=80=D0=B4=D0=B0?= =?UTF-8?q?=20=C2=AB=D0=91=D0=B8=D0=B7=D0=BD=D0=B5=D1=81-=D1=81=D1=8E?= =?UTF-8?q?=D0=B6=D0=B5=D1=82=D1=8B=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Зачем: - экран отвечал только графиками: итога за период не было, доли категорий читались по высоте столбиков, а известные пользователи лежали на нуле рядом с посетителями. - Что: - добавлены ряд крупных чисел (выручка, заказы, средний чек, посетители), кольцо долей категорий и линия доли известных пользователей; - средний чек и доля известных заведены метриками датасетов, знаменатель через `nullIf`: на пустом периоде деление Decimal на ноль в ClickHouse роняет панель; - фильтр «Период» сужает все панели, включая сверку по `order_day`; - `label_colors` закрепляет цвет за категорией и за рядами трафика; - деньги без копеек, единица в названии панели; подписи дат читаются как даты; сводная сверки развернута классами по строкам и уместилась без прокрутки; - обновлены справочник Superset и глава путеводителя. - Проверка: - `make lint`; - `superset import-directory /app/import --overwrite` на живом стенде, экран снят в браузере: девять панелей отрисованы, цвет категории одинаков на столбиках и в кольце; - период 03.06–06.06 сузил все панели, включая сводную по `order_day`; - `SUM(revenue) / nullIf(SUM(orders), 0)` на периоде без заказов возвращает NULL, без `nullIf` — исключение 153. Co-Authored-By: Claude Opus 5 (1M context) --- docs/architecture/superset.md | 57 +++++++- docs/handbook/superset.md | 20 +-- .../import/charts/big_number_avg_check.yaml | 19 +++ .../import/charts/big_number_orders.yaml | 19 +++ .../import/charts/big_number_revenue.yaml | 19 +++ .../import/charts/big_number_visitors.yaml | 19 +++ .../import/charts/known_users_share.yaml | 31 ++++ .../import/charts/purchase_vs_orders.yaml | 7 +- .../charts/revenue_by_day_and_category.yaml | 9 +- .../charts/revenue_share_by_category.yaml | 29 ++++ .../charts/visitors_and_known_users.yaml | 8 +- .../import/dashboards/business_stories.yaml | 138 +++++++++++++++++- .../datasets/ClickHouse/daily_traffic_v.yaml | 9 ++ .../datasets/ClickHouse/revenue_daily_v.yaml | 26 +++- 14 files changed, 378 insertions(+), 32 deletions(-) create mode 100644 infra/superset/import/charts/big_number_avg_check.yaml create mode 100644 infra/superset/import/charts/big_number_orders.yaml create mode 100644 infra/superset/import/charts/big_number_revenue.yaml create mode 100644 infra/superset/import/charts/big_number_visitors.yaml create mode 100644 infra/superset/import/charts/known_users_share.yaml create mode 100644 infra/superset/import/charts/revenue_share_by_category.yaml diff --git a/docs/architecture/superset.md b/docs/architecture/superset.md index a9f7c43..fd5df98 100644 --- a/docs/architecture/superset.md +++ b/docs/architecture/superset.md @@ -36,7 +36,7 @@ Airflow. В ClickHouse он не пишет ничего. | `metadata.yaml` | версия формата, `1.0.0`; больше в нем ничего нет | | `databases/clickhouse.yaml` | подключение к ClickHouse: URI без пароля и постоянный uuid | | `datasets/ClickHouse/*.yaml` | три витрины: `revenue_daily_v`, `purchase_vs_orders_v`, `daily_traffic_v` | -| `charts/*.yaml` | три графика: столбики выручки, сводная таблица сверки, линии трафика | +| `charts/*.yaml` | девять графиков: четыре крупных числа, столбики выручки и кольцо долей, сводная таблица сверки, линии трафика и доля известных | | `dashboards/business_stories.yaml` | дашборд «Бизнес-сюжеты» и раскладка панелей | Связаны файлы не путями, а uuid. Датасет называет `database_uuid`, график — @@ -46,20 +46,51 @@ Airflow. В ClickHouse он не пишет ничего. Uuid у стенда розданы рукой: общее начало `19600000-0000-4000-8000-`, дальше номер объекта в последнем блоке — `1`–`3` -у датасетов, `101`–`103` у графиков, `201` у дашборда +у датасетов, `101`–`109` у графиков, `201` у дашборда (`…-000000000101`). Экспорт из интерфейса приносит свои, сгенерированные; их заменяют на эти, иначе повторный импорт заведет вторую копию объекта вместо обновления первой. -Датасет несет русские имена колонок, формат денег и метрику — а график только +Датасет несет русские имена колонок, формат чисел и метрики — а график только ссылается на них по имени. Значит, подпись или формат правятся в одном месте, а -не в каждом графике. +не в каждом графике. Два исключения проверены на живом стенде, Superset 6.1. +Подписи оси график берет не из датасета, а из своего `y_axis_format`: без него +ось выручки уходит в «1.2M». И разрез сводной таблицы подписан именем колонки +(`mismatch_class`), хотя колонке даты в той же таблице русское имя достается. Датасеты объявлены физическими (`schema: dm`, `sql: null`), хотя за именем стоит представление ClickHouse. Импорт в источник не ходит и разницы между таблицей и представлением не знает, а виртуальный датасет со своим SQL просто повторил бы запрос, который уже живет в `sql/ddl/60-dm-views.sql`. +## Из чего собран экран + +Четыре строки панелей: + +- ряд крупных чисел — выручка, заказы, средний чек, посетители; +- выручка по дням и категориям, рядом доля категорий кольцом; +- сводная сверки purchase и заказов; +- посетители и известные пользователи, рядом доля известных. + +Правая панель пары отвечает на вопрос «сколько из целого» и берет цвета левой: +категория окрашена одинаково на столбиках и в кольце, доля известных — как +линия известных пользователей рядом. Цвет закрепляет `label_colors` в +`metadata` дашборда. Шесть категорий выписаны в него руками по каталогу +генератора (`generator/src/clickstream_generator/catalog.py`): седьмая +останется без закрепленного цвета, пока файл не поправят. + +Средний чек и доля известных считаются метриками датасета — +`SUM(revenue) / nullIf(SUM(orders), 0)` и то же для доли известных. Знаменатель +обернут не зря: на периоде без заказов деление Decimal на ноль в ClickHouse — +не `nan`, а исключение, и панель показала бы ошибку вместо пустоты. У витрины +выручки есть готовая колонка `aov`, но среднее по ней дало бы другое число: +день с тремя заказами получил бы тот же вес, что день с тремя сотнями. + +«Период» — единственный фильтр дашборда, тип `filter_time` с пустой целью +(`targets: [{}]`). Такой фильтр колонку не называет: он подставляет выбранный +период в то временное условие, которое уже стоит у каждого графика. Поэтому +сверка сужается по `order_day`, а остальные панели — по `report_date`. + ## Импорт при каждой инициализации Последняя строка `infra/superset/init.sh`: @@ -152,6 +183,17 @@ superset import-directory /app/import --overwrite завершается нулем в любом случае. Поэтому импорт проверяют глазами или запросом к API — но не тем, что команда отработала. +**Знак рубля приходит не из формата валюты.** Символ Superset берет у +`Intl.NumberFormat` по коду валюты и английской локали стенда: код `RUB` +печатается как «RUB», а знак «₽» вызов роняет, и форматирование молча +откатывается к числу без валюты. Поэтому единица стоит в названии панели — +«Выручка, ₽», — а метрика несет обычный формат `,d`. + +**`label_colors` знает имя ряда, а не подпись.** Для разреза имя ряда — это +значение колонки («Бытовая техника»), для графика без разреза — имя метрики +(`known_share`), а не ее русская подпись. Цвет, закрепленный за подписью +«Доля известных», не применяется. + **`--overwrite` синхронизирует датасет разрушительно.** Колонки и метрики берутся из YAML целиком: добавленная в интерфейсе метрика или подпись колонки исчезнет при следующем старте контейнера. Правка датасета — это правка файла. @@ -196,6 +238,13 @@ superset import-directory /app/import --overwrite каждой витрины, — поэтому фильтр периода дашборду разрешен, а кросс-фильтрация нет. +**Вкладки и блоки «что смотреть».** Вкладки были условным вариантом: их +заводят, когда экран перестает читаться одним взглядом. Четыре строки панелей +читаются сразу, поэтому вкладки спрятали бы половину экрана за щелчком без +выигрыша. Блок с текстом «что смотреть» рядом с панелью означал +бы, что панель сама себя не объясняет: тогда чинить надо название и подписи, а +не дописывать к ним пояснение. + **Пороги и раскраска панелей.** Правило [спеки](../specs/2026-07-30-stand-v2-realism.md), раздел 9: на дашборд смотрят глазами, красное и зеленое живет в проверках. diff --git a/docs/handbook/superset.md b/docs/handbook/superset.md index e91863c..412638b 100644 --- a/docs/handbook/superset.md +++ b/docs/handbook/superset.md @@ -1,21 +1,23 @@ # Немного Superset Superset показывает витрины слоя DM в виде графиков. К ClickHouse он -подключается пользователем `bi`. На дашборде стенда «Бизнес-сюжеты» три -графика: +подключается пользователем `bi`. Дашборд стенда «Бизнес-сюжеты» собран из трех +витрин: -| График | Витрина | +| Витрина | Что показывает | |---|---| -| «Выручка по дням и категориям» | `dm.revenue_daily_v` | -| «Сверка purchase и заказов» | `dm.purchase_vs_orders_v` | -| «Посетители и известные пользователи» | `dm.daily_traffic_v` | +| `dm.revenue_daily_v` | выручку, заказы и средний чек крупными числами, выручку по дням и категориям столбиками, доли категорий кольцом | +| `dm.purchase_vs_orders_v` | сводную сверки: сколько заказов дня попало в каждый класс расхождения | +| `dm.daily_traffic_v` | число посетителей крупно, посетителей и известных пользователей по дням, отдельно — долю известных | + +Слева от панелей стоит фильтр «Период». Он задает даты сразу для всех панелей. ## Как витрина становится графиком От витрины до экрана три объекта Superset: датасет → график → дашборд. Датасет -описывает витрину: задает русские имена колонок и формат денег. График -ссылается на эти имена и задает способ показа. Дашборд собирает готовые графики -на одном экране. +описывает витрину: задает русские имена колонок, формат чисел и показатели — +например, средний чек. График ссылается на эти имена и задает способ показа. +Дашборд собирает готовые графики на одном экране. ## Стендовые объекты и ваши diff --git a/infra/superset/import/charts/big_number_avg_check.yaml b/infra/superset/import/charts/big_number_avg_check.yaml new file mode 100644 index 0000000..cb98e75 --- /dev/null +++ b/infra/superset/import/charts/big_number_avg_check.yaml @@ -0,0 +1,19 @@ +slice_name: Средний чек, ₽ +description: null +certified_by: null +certification_details: null +viz_type: big_number_total +params: + viz_type: big_number_total + metric: avg_check + adhoc_filters: + - expressionType: SIMPLE + subject: report_date + operator: TEMPORAL_RANGE + comparator: No filter + clause: WHERE + header_font_size: 0.3 +cache_timeout: null +uuid: 19600000-0000-4000-8000-000000000106 +version: 1.0.0 +dataset_uuid: 19600000-0000-4000-8000-000000000001 diff --git a/infra/superset/import/charts/big_number_orders.yaml b/infra/superset/import/charts/big_number_orders.yaml new file mode 100644 index 0000000..bffdb37 --- /dev/null +++ b/infra/superset/import/charts/big_number_orders.yaml @@ -0,0 +1,19 @@ +slice_name: Заказы +description: null +certified_by: null +certification_details: null +viz_type: big_number_total +params: + viz_type: big_number_total + metric: orders + adhoc_filters: + - expressionType: SIMPLE + subject: report_date + operator: TEMPORAL_RANGE + comparator: No filter + clause: WHERE + header_font_size: 0.3 +cache_timeout: null +uuid: 19600000-0000-4000-8000-000000000105 +version: 1.0.0 +dataset_uuid: 19600000-0000-4000-8000-000000000001 diff --git a/infra/superset/import/charts/big_number_revenue.yaml b/infra/superset/import/charts/big_number_revenue.yaml new file mode 100644 index 0000000..d79811d --- /dev/null +++ b/infra/superset/import/charts/big_number_revenue.yaml @@ -0,0 +1,19 @@ +slice_name: Выручка, ₽ +description: null +certified_by: null +certification_details: null +viz_type: big_number_total +params: + viz_type: big_number_total + metric: revenue + adhoc_filters: + - expressionType: SIMPLE + subject: report_date + operator: TEMPORAL_RANGE + comparator: No filter + clause: WHERE + header_font_size: 0.3 +cache_timeout: null +uuid: 19600000-0000-4000-8000-000000000104 +version: 1.0.0 +dataset_uuid: 19600000-0000-4000-8000-000000000001 diff --git a/infra/superset/import/charts/big_number_visitors.yaml b/infra/superset/import/charts/big_number_visitors.yaml new file mode 100644 index 0000000..feafa53 --- /dev/null +++ b/infra/superset/import/charts/big_number_visitors.yaml @@ -0,0 +1,19 @@ +slice_name: Посетители +description: null +certified_by: null +certification_details: null +viz_type: big_number_total +params: + viz_type: big_number_total + metric: visitors + adhoc_filters: + - expressionType: SIMPLE + subject: report_date + operator: TEMPORAL_RANGE + comparator: No filter + clause: WHERE + header_font_size: 0.3 +cache_timeout: null +uuid: 19600000-0000-4000-8000-000000000107 +version: 1.0.0 +dataset_uuid: 19600000-0000-4000-8000-000000000003 diff --git a/infra/superset/import/charts/known_users_share.yaml b/infra/superset/import/charts/known_users_share.yaml new file mode 100644 index 0000000..f6721ad --- /dev/null +++ b/infra/superset/import/charts/known_users_share.yaml @@ -0,0 +1,31 @@ +slice_name: Доля известных пользователей +description: null +certified_by: null +certification_details: null +viz_type: echarts_timeseries_line +params: + viz_type: echarts_timeseries_line + x_axis: report_date + metrics: + - known_share + groupby: [] + adhoc_filters: + - expressionType: SIMPLE + subject: report_date + operator: TEMPORAL_RANGE + comparator: No filter + clause: WHERE + row_limit: 10000 + seriesType: line + show_legend: false + rich_tooltip: true + show_value: false + markerEnabled: true + markerSize: 6 + y_axis_format: .1% + x_axis_time_format: '%d.%m' + tooltipTimeFormat: '%d.%m.%Y' +cache_timeout: null +uuid: 19600000-0000-4000-8000-000000000109 +version: 1.0.0 +dataset_uuid: 19600000-0000-4000-8000-000000000003 diff --git a/infra/superset/import/charts/purchase_vs_orders.yaml b/infra/superset/import/charts/purchase_vs_orders.yaml index a6bdc34..2f41e09 100644 --- a/infra/superset/import/charts/purchase_vs_orders.yaml +++ b/infra/superset/import/charts/purchase_vs_orders.yaml @@ -6,9 +6,9 @@ viz_type: pivot_table_v2 params: viz_type: pivot_table_v2 groupbyRows: - - order_day - groupbyColumns: - mismatch_class + groupbyColumns: + - order_day metrics: - order_count adhoc_filters: @@ -23,8 +23,7 @@ params: colOrder: key_a_to_z order_desc: true row_limit: 10000 - valueFormat: SMART_NUMBER - date_format: smart_date + date_format: '%d.%m.%Y' cache_timeout: null uuid: 19600000-0000-4000-8000-000000000102 version: 1.0.0 diff --git a/infra/superset/import/charts/revenue_by_day_and_category.yaml b/infra/superset/import/charts/revenue_by_day_and_category.yaml index c7351a6..1cc7e3f 100644 --- a/infra/superset/import/charts/revenue_by_day_and_category.yaml +++ b/infra/superset/import/charts/revenue_by_day_and_category.yaml @@ -1,4 +1,4 @@ -slice_name: Выручка по дням и категориям +slice_name: Выручка по дням и категориям, ₽ description: null certified_by: null certification_details: null @@ -20,10 +20,13 @@ params: stack: Stack orientation: vertical show_legend: true + legendType: plain + legendOrientation: bottom rich_tooltip: true show_value: false - y_axis_format: ',.2f' - x_axis_time_format: smart_date + y_axis_format: ',d' + x_axis_time_format: '%d.%m' + tooltipTimeFormat: '%d.%m.%Y' cache_timeout: null uuid: 19600000-0000-4000-8000-000000000101 version: 1.0.0 diff --git a/infra/superset/import/charts/revenue_share_by_category.yaml b/infra/superset/import/charts/revenue_share_by_category.yaml new file mode 100644 index 0000000..d11e349 --- /dev/null +++ b/infra/superset/import/charts/revenue_share_by_category.yaml @@ -0,0 +1,29 @@ +slice_name: Доля категорий в выручке +description: null +certified_by: null +certification_details: null +viz_type: pie +params: + viz_type: pie + groupby: + - product_category + metric: revenue + adhoc_filters: + - expressionType: SIMPLE + subject: report_date + operator: TEMPORAL_RANGE + comparator: No filter + clause: WHERE + row_limit: 10000 + sort_by_metric: true + donut: true + innerRadius: 30 + outerRadius: 70 + show_labels: true + labels_outside: false + label_type: percent + show_legend: false +cache_timeout: null +uuid: 19600000-0000-4000-8000-000000000108 +version: 1.0.0 +dataset_uuid: 19600000-0000-4000-8000-000000000001 diff --git a/infra/superset/import/charts/visitors_and_known_users.yaml b/infra/superset/import/charts/visitors_and_known_users.yaml index e0c06f3..594aaf0 100644 --- a/infra/superset/import/charts/visitors_and_known_users.yaml +++ b/infra/superset/import/charts/visitors_and_known_users.yaml @@ -17,12 +17,16 @@ params: comparator: No filter clause: WHERE row_limit: 10000 - seriesType: echarts_timeseries_line + seriesType: line show_legend: true + legendOrientation: bottom rich_tooltip: true show_value: false + markerEnabled: true + markerSize: 6 y_axis_format: ',d' - x_axis_time_format: smart_date + x_axis_time_format: '%d.%m' + tooltipTimeFormat: '%d.%m.%Y' cache_timeout: null uuid: 19600000-0000-4000-8000-000000000103 version: 1.0.0 diff --git a/infra/superset/import/dashboards/business_stories.yaml b/infra/superset/import/dashboards/business_stories.yaml index f7b17c5..59ef41e 100644 --- a/infra/superset/import/dashboards/business_stories.yaml +++ b/infra/superset/import/dashboards/business_stories.yaml @@ -19,9 +19,79 @@ position: parents: - ROOT_ID children: + - ROW-kpi - ROW-revenue - ROW-pvo - ROW-traffic + ROW-kpi: + id: ROW-kpi + type: ROW + parents: + - ROOT_ID + - GRID_ID + children: + - CHART-kpi-revenue + - CHART-kpi-orders + - CHART-kpi-avg-check + - CHART-kpi-visitors + meta: + background: BACKGROUND_TRANSPARENT + CHART-kpi-revenue: + id: CHART-kpi-revenue + type: CHART + parents: + - ROOT_ID + - GRID_ID + - ROW-kpi + children: [] + meta: + chartId: 4 + height: 20 + width: 3 + sliceName: Выручка, ₽ + uuid: 19600000-0000-4000-8000-000000000104 + CHART-kpi-orders: + id: CHART-kpi-orders + type: CHART + parents: + - ROOT_ID + - GRID_ID + - ROW-kpi + children: [] + meta: + chartId: 5 + height: 20 + width: 3 + sliceName: Заказы + uuid: 19600000-0000-4000-8000-000000000105 + CHART-kpi-avg-check: + id: CHART-kpi-avg-check + type: CHART + parents: + - ROOT_ID + - GRID_ID + - ROW-kpi + children: [] + meta: + chartId: 6 + height: 20 + width: 3 + sliceName: Средний чек, ₽ + uuid: 19600000-0000-4000-8000-000000000106 + CHART-kpi-visitors: + id: CHART-kpi-visitors + type: CHART + parents: + - ROOT_ID + - GRID_ID + - ROW-kpi + children: [] + meta: + chartId: 7 + height: 20 + width: 3 + sliceName: Посетители + uuid: 19600000-0000-4000-8000-000000000107 ROW-revenue: id: ROW-revenue type: ROW @@ -30,6 +100,7 @@ position: - GRID_ID children: - CHART-revenue + - CHART-revenue-share meta: background: BACKGROUND_TRANSPARENT CHART-revenue: @@ -43,9 +114,23 @@ position: meta: chartId: 1 height: 50 - width: 12 - sliceName: Выручка по дням и категориям + width: 8 + sliceName: Выручка по дням и категориям, ₽ uuid: 19600000-0000-4000-8000-000000000101 + CHART-revenue-share: + id: CHART-revenue-share + type: CHART + parents: + - ROOT_ID + - GRID_ID + - ROW-revenue + children: [] + meta: + chartId: 8 + height: 50 + width: 4 + sliceName: Доля категорий в выручке + uuid: 19600000-0000-4000-8000-000000000108 ROW-pvo: id: ROW-pvo type: ROW @@ -66,7 +151,7 @@ position: children: [] meta: chartId: 2 - height: 50 + height: 44 width: 12 sliceName: Сверка purchase и заказов uuid: 19600000-0000-4000-8000-000000000102 @@ -78,6 +163,7 @@ position: - GRID_ID children: - CHART-traffic + - CHART-known-share meta: background: BACKGROUND_TRANSPARENT CHART-traffic: @@ -91,15 +177,57 @@ position: meta: chartId: 3 height: 50 - width: 12 + width: 6 sliceName: Посетители и известные пользователи uuid: 19600000-0000-4000-8000-000000000103 + CHART-known-share: + id: CHART-known-share + type: CHART + parents: + - ROOT_ID + - GRID_ID + - ROW-traffic + children: [] + meta: + chartId: 9 + height: 50 + width: 6 + sliceName: Доля известных пользователей + uuid: 19600000-0000-4000-8000-000000000109 metadata: color_scheme: supersetColors + label_colors: + Товары для дома: '#1FA8C9' + Текстиль: '#454E7C' + Посуда: '#5AC189' + Бытовая техника: '#FF7F44' + Детские товары: '#E04355' + Одежда и обувь: '#A868B7' + visitors: '#1FA8C9' + known_users: '#454E7C' + known_share: '#454E7C' cross_filters_enabled: false chart_configuration: {} expanded_slices: {} default_filters: '{}' - native_filter_configuration: [] + native_filter_configuration: + - id: NATIVE_FILTER-period + name: Период + filterType: filter_time + type: NATIVE_FILTER + targets: + - {} + controlValues: + enableEmptyFilter: false + defaultDataMask: + extraFormData: {} + filterState: {} + ownState: {} + cascadeParentIds: [] + scope: + rootPath: + - ROOT_ID + excluded: [] + description: '' theme_uuid: null version: 1.0.0 diff --git a/infra/superset/import/datasets/ClickHouse/daily_traffic_v.yaml b/infra/superset/import/datasets/ClickHouse/daily_traffic_v.yaml index 082a323..8b126f9 100644 --- a/infra/superset/import/datasets/ClickHouse/daily_traffic_v.yaml +++ b/infra/superset/import/datasets/ClickHouse/daily_traffic_v.yaml @@ -36,6 +36,15 @@ metrics: currency: null extra: null warning_text: null +- metric_name: known_share + verbose_name: Доля известных + metric_type: null + expression: SUM(known_users) / nullIf(SUM(visitors), 0) + description: null + d3format: .1% + currency: null + extra: null + warning_text: null columns: - column_name: _load_ts verbose_name: Время загрузки diff --git a/infra/superset/import/datasets/ClickHouse/revenue_daily_v.yaml b/infra/superset/import/datasets/ClickHouse/revenue_daily_v.yaml index a463b33..1c47107 100644 --- a/infra/superset/import/datasets/ClickHouse/revenue_daily_v.yaml +++ b/infra/superset/import/datasets/ClickHouse/revenue_daily_v.yaml @@ -23,10 +23,26 @@ metrics: metric_type: null expression: SUM(revenue) description: null - d3format: ',.2f' - currency: - symbol: ₽ - symbolPosition: suffix + d3format: ',d' + currency: null + extra: null + warning_text: null +- metric_name: orders + verbose_name: Заказы + metric_type: null + expression: SUM(orders) + description: null + d3format: ',d' + currency: null + extra: null + warning_text: null +- metric_name: avg_check + verbose_name: Средний чек + metric_type: null + expression: SUM(revenue) / nullIf(SUM(orders), 0) + description: null + d3format: ',d' + currency: null extra: null warning_text: null columns: @@ -44,7 +60,7 @@ columns: datetime_format: null extra: null - column_name: aov - verbose_name: Средний чек + verbose_name: Средний чек за день и категорию is_dttm: false is_active: true type: DECIMAL(18, 2) -- 2.54.0