docs(labs): добавлены три расследования расхождений выручки

Зачем: дать практику сверки событий покупки с заказами магазина.
Что: задания о потерях событий, повторах покупок и расхождении состава корзин.
Проверка: запросы под analyst на ClickHouse 26.3.17.56; счетчики, суммы и точный разбор JSON сошлись. make lint и независимая техническая проверка пройдены.
This commit is contained in:
ddadmin committed 2026-09-22 03:46:45 -04:00
1 parent ddb186f841
commit 2502277af1
3 files changed
+214

No files matched your search

@@ -0,0 +1,70 @@
# Какая позиция объясняет разницу в сумме
**Чему учит:** перейти от расхождения суммы заказа к конкретному товару и
проверить объяснение с точностью до копейки.
Факультатив доступен после ступени 1. В DBeaver используйте пользователя
`analyst` из [инструкции подключения](../../../README.md#подключиться-из-dbeaver).
Дождитесь завершения `etl_pipeline`; оставьте `world_live` на паузе и
дождитесь уже начатых прогонов.
## Найдите заказ
В `dm.purchase_vs_orders_v` выберите один заказ с
`mismatch_class = 'amount_delta'`. Возьмите закрытый день: `order_day`
не позднее `max(snapshot_date) - 6` из `ods.order_v`. Сохраните `order_id`,
`order_day`, `declared_revenue` и `items_total`.
Найдите этот заказ в `dds.order_v`. Сопоставьте `items_total`, `discount`,
`delivery` и `total`. Как связаны эти суммы? Объясните, почему клиентскую
`declared_revenue` нужно сравнивать с `items_total`, чтобы искать разницу
именно в составе корзины.
## Разберите позиции с двух сторон
Найдите событие покупки в `ods.event_v`: `purchaseID[1]` совпадает с номером
заказа, `EventDate` — с выбранным днем, `EventType = 'purchase'`.
Откройте поле `ecommerce`. Внутри JSON массив `purchase.products` содержит
позиции клиента с полями `id`, `price` и `quantity`.
Разверните этот массив в строки и получите артикул, точную цену, количество
и стоимость каждой позиции. Для разбора пригодятся `JSONExtractArrayRaw`
и `JSONExtract`, для разворачивания массива — `ARRAY JOIN`.
Деньги извлекайте как `Decimal` с двумя знаками после запятой.
С другой стороны используйте массивы `item_sku`, `item_price` и
`item_quantity` заказа в `dds.order_v`. Элементы с одним индексом относятся
к одной позиции; при разворачивании сохраняйте эту связь.
Сопоставьте позиции по артикулу так, чтобы остались видны товары,
присутствующие только с одной стороны. Покажите, какие позиции совпали,
а какая объясняет разницу. В результате нужны строки товаров, а не только
две итоговые суммы.
## Проверьте объяснение
Подтвердите три равенства:
- сумма стоимостей клиентских позиций равна `declared_revenue`;
- сумма стоимостей позиций магазина равна `items_total`;
- стоимость отсутствующей у магазина позиции равна
`declared_revenue - items_total`.
Затем сравните точные цены из JSON с готовым массивом `productPrice`
события. По [формату выгрузки](../../formats/clickstream-event.md) цены в нем
округлены до целых рублей. Покажите на своей корзине, что потеряется при
расчете по этому массиву. Если все цены выбранной корзины целые, возьмите
еще один заказ с расхождением и дробной ценой.
В коротком объяснении назовите заказ, товар, количество, цену и разницу.
Отделите то, что подтверждают данные, от причины, которую по ним установить
нельзя: отсутствие позиции в заказе видно, а причину ее удаления источник
отдельным полем не сообщает.
## Что должно получиться
- [ ] позиции клиента и магазина сопоставлены по артикулам;
- [ ] все три равенства сходятся до копейки;
- [ ] найден пример потери точности в готовом массиве цен;
- [ ] расхождение объяснено конкретной позицией, а скидка и доставка
отделены от сравнения корзин.