# Заказы

## Список (`/admin/shop/orders`)

Табы по статусу заказа со счётчиками, поиск по номеру / имени / email / телефону. В таблице — номер, дата+время, клиент, кол-во позиций, итоговая сумма, статус оплаты, статус заказа, источник (web/admin/phone/api).

## Карточка заказа (`/admin/shop/orders/{id}`)

Двухколоночный layout:

- **Слева** — позиции заказа (товар, цена, кол-во, сумма), сводка с подытогом/доставкой/скидкой/налогом/итого, форма редактирования деталей (метод доставки, стоимость, метод оплаты, скидка, контактные данные клиента, внутренняя заметка), лента истории событий.
- **Справа** (sticky) — селект смены статуса заказа с комментарием, селект смены статуса оплаты, таймстампы (paid_at, shipped_at, delivered_at), мини-карточка клиента с быстрой ссылкой на профиль.

### Статусы заказа

| Код | Подпись | Когда |
|---|---|---|
| `new` | Новый | Только что оформлен |
| `paid` | Оплачен | Получена оплата |
| `shipped` | Отправлен | Авто-выставляет `shipped_at`, если пусто |
| `delivered` | Доставлен | Авто-выставляет `delivered_at` |
| `cancelled` | Отменён | Не учитывается в выручке/агрегатах клиента |

### Статусы оплаты (отдельно от заказа)

| Код | Подпись | Когда |
|---|---|---|
| `pending` | Ожидает оплаты | По умолчанию |
| `paid` | Оплачен | Авто-выставляет `paid_at` |
| `refunded` | Возврат | |
| `cancelled` | Отменена | |

### История событий (`shop_order_history`)

На каждое значимое действие пишется запись с типом `created / status_changed / payment_changed / note / item_changed`. В карточке отображается лентой: «Статус: Новый → Оплачен», «Заметка: …», с автором (admin user) и таймстампом. Свободные заметки добавляются через форму прямо в ленте.

### Авто-связь с клиентами

При сохранении заказа (вручную или с витрины) `CustomerRepo::upsertFromOrder()` находит/создаёт клиента в `shop_customers` по email и привязывает к заказу через `customer_id`. После любого изменения статуса вызывается `recalcAggregates()` — пересчитывает `orders_count`, `total_spent`, `last_order_at` (исключая отменённые).

## Ручное создание заказа (`/admin/shop/orders/create`)

Форма с автокомплитом:

- **Поиск клиента** — начни вводить имя/email/телефон, выбор из выпадающего списка автоматически заполнит контакты. Если клиент новый — оставляешь пустым и заполняешь поля сам.
- **Поиск товара** — начни вводить название/SKU/ID. Выбор добавляет позицию с актуальной ценой из БД (источник истины — не доверяешь клиентскому полю). Кнопка «Добавить произвольную позицию» — для товаров не из каталога.
- **Сводка** справа — live-пересчёт итога при изменении количества/цены/доставки/скидки/налога. При выборе метода доставки авто-подставляется его стоимость.
- **Источник** проставляется как `admin`, источник `web` — только для оформлений с витрины.

После создания → редирект на карточку с flash «Заказ создан: ORD-XXXXX».

## Префикс номера заказа

Настраивается в `Магазин → Настройки → Заказы → Префикс номера`. По умолчанию `ORD-`. Допускается любая алфанумерическая строка с дефисом длиной 4–64 символа: `ORD-`, `CEL-`, `INV-`, `#`. После префикса — 8 hex-символов.

## База

- `shop_orders` — заказ. Ключевые поля: `number` (уникальный), `customer_id`, `customer_*` (snapshot контактов на момент покупки), `subtotal`, `discount`, `tax`, `shipping_cost`, `total`, `currency`, `status`, `payment_status`, `shipping_method_id/title`, `payment_method_id/title`, `promo_code`, `admin_note`, `source`, `paid_at`, `shipped_at`, `delivered_at`.
- `shop_order_items` — позиции с `variation_id`, `variation_label`, `product_title`, `product_sku`, `price`, `quantity`, `subtotal`. Snapshot — название/SKU остаются даже если товар удалили.
- `shop_order_history` — лента событий с `event`, `from_value`, `to_value`, `comment`, `user_id`, `created_at`.
