docs(orders): уточнён формат слепка и временные поля
- Зачем: - аудит источника нельзя смешивать с бизнес-временем и `_load_ts` ClickHouse. - Что: - зафиксированы JSON-контракт слепка, порядок ключей и намеренное различие `Array(Float64)` и `Decimal`. - разведены бизнес-время, аудит источника и загрузка; уточнены слой ODS, `snapshot_date` и технический ключ партиции. - добавлены термины словаря и исследование точного миллисекундного формата с проверками ClickHouse. - Проверка: - выполнен `git diff --cached --check`.
This commit is contained in:
@@ -190,17 +190,34 @@ Ecommerce (заполнены только у торговых событий):
|
||||
выручка дня D «дышит» K дней, потом замерзает. Боевой аналог окна есть и у
|
||||
трекеров: лог Метрики «доформировывается» ещё около трёх дней.
|
||||
- Запись слепка — состояние заказа на момент выгрузки, «родной» экспорт
|
||||
бэкенда в snake_case:
|
||||
бэкенда в snake_case. Таблица задаёт тип после разбора в ODS:
|
||||
|
||||
| Поле | Тип | Комментарий |
|
||||
| Поле | Тип в ODS | Комментарий |
|
||||
|---|---|---|
|
||||
| `order_id` | String | номер заказа; равен клиентскому `purchaseID` |
|
||||
| `user_id` | UInt64 | пользователь магазина — мост к склейке |
|
||||
| `status` | String | `created` → `paid` → `cancelled` |
|
||||
| `created_at`, `updated_at` | DateTime | |
|
||||
| `created_at`, `updated_at` | DateTime64(3, 'UTC') | аудит строки в БД источника: создание и последнее изменение; не бизнес-время покупки и не время загрузки в ClickHouse |
|
||||
| `items_total`, `discount`, `delivery`, `total` | Decimal(18,2) | деньги бэкенда — в Decimal |
|
||||
| `items` | String | позиции вложенным JSON: `[{sku, qty, price}]` |
|
||||
| `snapshot_date` | Date | дата слепка (день выгрузки) |
|
||||
| `items` | String | сырой текст массива позиций `[{sku, qty, price}]`, извлечённый из внешнего JSON |
|
||||
| `snapshot_date` | Date | завершившийся модельный день, состояние которого снято на исходящей границе суток |
|
||||
|
||||
На проводе один заказ — один документ JSON. Деньги, включая `items[].price`,
|
||||
передаются строками с ровно двумя знаками после точки; `created_at` и
|
||||
`updated_at` — строками RFC 3339 в UTC с обязательными миллисекундами
|
||||
(`YYYY-MM-DDTHH:mm:ss.SSSZ`); `snapshot_date` — строкой `YYYY-MM-DD`;
|
||||
`items` — обычным массивом JSON, не строкой с JSON внутри. Порядок внешних
|
||||
ключей совпадает с порядком полей в таблице контракта, у позиции — `sku`,
|
||||
`qty`, `price`: так байты воспроизводимы без сортировки ключей. Разница с
|
||||
кликстримом намеренна: там значения `purchaseRevenue` приезжают JSON-числами
|
||||
и разбираются как `Array(Float64)`, а бэкенд передаёт деньги строками для
|
||||
точного `Decimal`. Это показывает расхождение представлений денег в двух
|
||||
источниках.
|
||||
Запись собирает явная функция существующего канонического сериализатора:
|
||||
один словарь с вложенным списком и один `orjson.dumps`, без универсального
|
||||
слоя кодеков.
|
||||
Обоснование и проверка разбора — в
|
||||
[исследовании формата](../research/2026-08-16-order-snapshot-wire-format.md).
|
||||
|
||||
- Приём идемпотентный, но дедуп расщеплён на два слоя:
|
||||
- `ods.order_snapshot` — партиция по `snapshot_date`, **без дедупа**,
|
||||
@@ -208,7 +225,8 @@ Ecommerce (заполнены только у торговых событий):
|
||||
партиции дня слепка, а не ReplacingMergeTree.
|
||||
- Дедуп до последней версии — **argMax** в трансформации при сборке
|
||||
`dds.order`. `dds.order` — единственная дедуплицированная таблица:
|
||||
партиция по дню заказа (`toDate(created_at)`),
|
||||
партиция по дню создания строки источника (`toDate(created_at)`) — это
|
||||
стабильный технический ключ, а не бизнес-день покупки,
|
||||
ReplacingMergeTree(`updated_at`), `ORDER BY order_id` — заказ всегда
|
||||
лежит в одной партиции, дедуп работает.
|
||||
|
||||
@@ -394,7 +412,7 @@ README.
|
||||
| ODS | `ods.order_snapshot` (+`_errors`) | слепки заказов как приехали, партиция по `snapshot_date`, без дедупа |
|
||||
| DDS | `dds.session` | сборка сессий из событий (наследник `dds.click`) |
|
||||
| DDS | `dds.event_v` | представление над `ods.event`: snake_case-имена, расшифровка кодов `DeviceCategory`; витрины DM читают его, а не ODS напрямую |
|
||||
| DDS | `dds.order` | единственная дедуплицированная таблица заказа: партиция по дню заказа (`toDate(created_at)`), ReplacingMergeTree(`updated_at`), `ORDER BY order_id`, дедуп до последней версии — argMax в трансформации при сборке |
|
||||
| DDS | `dds.order` | единственная дедуплицированная таблица заказа: партиция по техническому дню создания строки источника (`toDate(created_at)`), ReplacingMergeTree(`updated_at`), `ORDER BY order_id`, дедуп до последней версии — argMax в трансформации при сборке |
|
||||
| DDS | `dds.identity_map` | карта кука↔пользователь |
|
||||
| DDS | словарь `products` | каталог из CSV |
|
||||
| DM | витрины `dm.*_v`, `dm.dq_summary` | см. ниже |
|
||||
|
||||
Reference in New Issue
Block a user