feat(generator): заказы дня — проекция покупок с деньгами магазина
- Зачем: - тикет #90: второй источник должен смотреть на торговую половину дня глазами бэкенда — заказ есть проекция покупки, а не второе порождение; учебный результат — два источника согласованы по построению, а не сверкой. - Что: - `commerce` отдаёт вторым выходом покупки дня: номер заказа, корзину, выручку клиента, промокод и человека за кукой; новых бросков в подпоток `COMMERCE` не добавилось, события дня не сдвинулись. - заведена заказная сторона: подпоток `ORDERS` на позиции 2 дерева зерна (прежнее мёртвое имя `DISCREPANCIES`), ветвление — по дню рождения заказа; `LATECOMERS` не тронут, его наполнит этап 6. - новый модуль `orders.py`: деньги заказа целыми копейками — `items_total` из корзины, `discount` по таблице «код → скидка» (округление вниз), `delivery` броском по таблице весов на полную длину дня, `total` = `items_total` − `discount` + `delivery`. - план состава завёл `person_id` — последним броском когорты, после паспортов: вторая кука пары повторяет ID своего человека, заказ показывает его как `user_id`, в событие Метрики он не попадает. - `world`: окно изменяемости `ORDER_WINDOW_DAYS` = 7 рядом с D0 и поясом, черновая таблица стоимости доставки. - слепок дня в тестах сторожит обе половины: заказы сравниваются наравне с потоком событий. - доки: имя подпотока заказной стороны и состав денег заказа записаны в `docs/architecture/orders`, README генератора знает про новый модуль. - Проверка: - из `generator/`: make lint, make typecheck, make test (417 тестов); в корне — make lint. - опись мира не покраснела: байты восьми дней те же, заказная сторона события не сдвинула. Closes #90 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -52,19 +52,39 @@ def readable(column: NDArray[Any]) -> list[Any]:
|
||||
return column.tolist()
|
||||
|
||||
|
||||
def orders(events: day.Day) -> list[list[Any]]:
|
||||
"""Заказы дня в сравнимом виде: строка на заказ, все его поля."""
|
||||
theirs = events.orders
|
||||
return [
|
||||
[
|
||||
theirs.order_id[number],
|
||||
int(theirs.user_id[number]),
|
||||
theirs.product[number].tolist(),
|
||||
theirs.quantity[number].tolist(),
|
||||
int(theirs.items_total[number]),
|
||||
int(theirs.discount[number]),
|
||||
int(theirs.delivery[number]),
|
||||
int(theirs.total[number]),
|
||||
]
|
||||
for number in range(len(theirs))
|
||||
]
|
||||
|
||||
|
||||
def snapshot(events: day.Day) -> dict[str, Any]:
|
||||
"""Слепок дня для сравнений: всё, что день отдал наружу.
|
||||
|
||||
Порядок колонок в слепке живёт отдельным списком: словари сравниваются
|
||||
без оглядки на него, а порядок — часть обещания (он же порядок
|
||||
контракта схемы). Швы `page` и `product` — тоже часть отдаваемого, и
|
||||
сторожить их надо тем же слепком, а не отдельной памятью.
|
||||
контракта схемы). Швы `page` и `product` — тоже часть отдаваемого, как
|
||||
и вторая половина дня, заказы: сторожить их надо тем же слепком, а не
|
||||
отдельной памятью.
|
||||
"""
|
||||
return {
|
||||
"order": list(events.columns),
|
||||
"values": [readable(column) for column in events.columns.values()],
|
||||
"page": events.page.tolist(),
|
||||
"product": events.product.tolist(),
|
||||
"orders": orders(events),
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +111,7 @@ def test_the_snapshot_notices_everything_the_day_hands_out(weekday: day.Day):
|
||||
columns=dict(reversed(list(weekday.columns.items()))),
|
||||
page=weekday.page,
|
||||
product=weekday.product,
|
||||
orders=weekday.orders,
|
||||
)
|
||||
assert snapshot(reordered) != original
|
||||
|
||||
@@ -101,6 +122,12 @@ def test_the_snapshot_notices_everything_the_day_hands_out(weekday: day.Day):
|
||||
shifted[0] += 1
|
||||
assert snapshot(replace(weekday, page=shifted)) != original
|
||||
|
||||
paid = weekday.orders.total.copy()
|
||||
paid[0] += 1
|
||||
assert snapshot(replace(weekday, orders=replace(weekday.orders, total=paid))) != (
|
||||
original
|
||||
)
|
||||
|
||||
|
||||
def test_a_day_is_a_pure_function_of_the_seed_and_the_day():
|
||||
first = snapshot(day.stream(CANONICAL_SEED, 3))
|
||||
|
||||
Reference in New Issue
Block a user