## Ответ

Сумма заказа живёт **на обеих сторонах**, и стороны законно расходятся:
клиентское событие несёт объявленную сумму (то, что сайт продиктовал трекеру
через dataLayer — до пересчёта на бэкенде), заказ бэкенда — итоговую правду
со статусами. Правило стенда: **поведение и атрибуцию считаем по трекеру,
деньги — по бэкенду**. Правило выучивается на конфликте: суммы у менти
не сойдутся, и он сам раскопает почему.

### Клиентская сторона (широкое событие, рамка #18)

- Таксономия торговых событий: `pageview` + `add_to_cart` + `purchase`.
  Полный словарь Метрики (`detail`, `remove`, `impressions`) не берём:
  механика та же, объём массивов большой, новых идей нет — остаётся теорией
  в документе о реализме.
- `purchase` несёт `purchaseID/Revenue/Currency/Coupon` + массивы `product*`
  состава заказа + сырую строку `ecommerce` (по образцу выгрузки Метрики,
  фактура — #27).
- `add_to_cart` — массивы `product*` с одним товаром. Оживают мёртвые
  счётчики `purchases`/`add_to_carts` в `v_utm_effectiveness` без правки витрины.

### Сторона бэкенда (второй источник, рамка #18)

- **Формат выгрузки: полный ежедневный слепок заказов в пределах окна
  изменяемости K дней.** Запись = снапшот заказа: `order_id`, `user_id`,
  времена, `status` (`created`/`paid`/`cancelled`), `updated_at`, итоговые
  суммы (товары / скидка / доставка / итого) + **позиции вложенным JSON**
  (`items: [{sku, qty, price}]`) — «родной» экспорт бэкенда, а не диалект
  Метрики.
- Обоснование слепка (а не инкремента): очень частый боевой формат;
  идемпотентный приём и самовосстановление (пропущенный день ничего не
  ломает); дедуп до последней версии становится обязательным с первого дня.
  Окно K делает объём защитимым (за окном заказ неизменяем — возить незачем)
  и даёт границу пересчёта: выручка дня D «дышит» K дней, потом замерзает.
- Приём: дедуп через `ReplacingMergeTree`/`argMax`; разбор JSON-позиций —
  **один раз** в трансформации ODS → DDS, дальше витрины работают с плоскими
  массивами. Это единственный носитель навыка «вложенный JSON в ClickHouse»
  в стенде.
- В `docs/generator-realism.md` — честный абзац trade-off «инкремент экономнее,
  слепок надёжнее» и сноска про compacted topic как родной Kafka-паттерн
  для состояния сущности.

### Сверка

- **Ключ: клиентский `purchaseID` = `order_id` бэкенда** (магазин знает номер
  заказа на `/confirmation` — как `actionField.id` у Метрики).
- Конструируемые расхождения — перечислимый список из четырёх причин,
  детерминированных от seed:
  - **A. Отмена** — `purchase` есть, заказ дошёл до `status='cancelled'`
    (бесплатно из статусов);
  - **B. Потерянное событие** — заказ есть, `purchase` не доехал
    (вероятность в генераторе);
  - **C. Дельта суммы** — систематическая, по построению: клиент объявляет
    сумму товаров до промокода и доставки, бэкенд — итог; менти может вывести
    формулу связи;
  - **D. Дубль события** — повторный `purchase` от обновления
    `/confirmation` (вероятность).
- Пятый эффект бесплатно даёт формат доставки: **опоздание** (заказ впервые
  появляется в слепке D+1/D+2) — «вчера не сходилось, сегодня сошлось».
- Не берём: сироту-фрод (дублирует B механически) и расхождение часов
  клиент/сервер — это жители тумана «Грязь в данных», придут своим тикетом.

### Слои и витрины

- DDS: одна новая сущность `dds.order` (последняя версия заказа, позиции
  разобраны в массивы). `purchase` отдельной сущности не получает — это
  строка широкого события.
- DM, три роли: **выручка** (`v_revenue_daily`, по категориям через `dictGet`
  каталога) — строится только от заказов; **сверка**
  (`v_purchase_vs_orders`) — FULL OUTER JOIN по ключу с классификатором
  расхождения; **атрибуция** (`v_utm_effectiveness`) — остаётся клиентской,
  плюс объявленная выручка по UTM. Точный состав колонок — в спеку (#17).

### Эталонный мир

Пересборка артефакта неизбежна и уже оплачена решением #18; этот тикет
нагружает её смыслом: манифест расширяется контрольными числами заказной
стороны — заказы и выручка по дням, и ровно N потерянных / M дублей /
K отмен для самопроверки лабы сверки. Политика версионирования артефакта
здесь не решается (пункт тумана карты).

### Ограничения исполнения и страховочные срезы

Аудитория — джун после базовой программы: расхождения — перечислимый список,
не хаос. Если при сборке спеки (#17) суммарный объём испугает, резать в
порядке: (1) статусы сузить до `created`/`cancelled` — урок дедупа держится
на самом слепке; (2) расхождения вводить поэтапно — сначала A+C, потом B+D;
(3) окно K сделать константой мира, а не параметром.

### Отклонено по дороге

Событийный лог заказов (сборка автомата — дальше от типовой работы DE),
CDC-формат (имитация Debezium без Debezium), шапка+строки (воскрешает склейку
по ключам), отдельный поток возвратов, полный словарь торговых событий
Метрики, механика Sign/CollapsingMergeTree (остаётся кандидатом на потом,
её дом — клиентская сторона, поток визитов Метрики Про, не заказы).

Фактура: `docs/research/2026-07-26-yandex-clickstream-format.md` (#27),
резолюция «Модель данных» (#18).
