О проекте
Команда: Ctrl-Z
Кейс HackAlem.ai: Торговля — Электрокомплект · ekt.kz
Стадия: Доведённый продукт
Задача кейса: AI-консультант по каталогу ekt.kz: товары, аналоги, цены, остатки, корзина
Суть
Витрина ekt.kz с ИИ-консультантом: поиск и фильтры по каталогу, сравнение, подбор аналогов, корзина с подтверждением каждого изменения, демо-оформление заявки, экспорт подборки в XLSX/PDF, интерфейс на RU/KZ/EN.
Как устроено
Снимок из 100 реальных карточек (data/catalog.json, скрипт sync-catalog.mjs) плюс свежая проверка карточки через API ekt.kz (/api/products/detail) на сервере Vinext/Cloudflare Worker. Модель через Chat Completions-совместимый endpoint с function tools читает каталог. Изменения корзины идут двумя шагами: серверное предложение с токеном и сроком 5 минут, затем подтверждение с повторной проверкой цены и остатка; запись в D1 защищена сравнением revision. Аналог выдаётся только при совпадении группы и минимум двух критических параметров.
Ключевые решения
- function calling
- двухэтапное подтверждение корзины (токен + TTL)
- optimistic concurrency (revision) в D1
- правила подбора аналогов по критическим параметрам
- разбор спецификаций из вложений
- экспорт XLSX/PDF
Особенности
Серьёзная защита корзины: HttpOnly-сессия, проверка Origin, одноразовое предложение с TTL, повторное чтение API перед записью и revision-сравнение от гонок. Честная обработка неизвестных значений: при противоречии номинала аналоги не выдаются, нули вместо пропусков не подставляются. Много тестов, в том числе адаптера ИИ на подставных ответах.
Стек
TypeScript · React · Vinext · Cloudflare Workers · Cloudflare D1 · Drizzle ORM · shadcn/ui · Node.js
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-66bc5b7b-ctrl-z.
README
README.mdЭлектрокомплект — консультант по каталогу
Проект команды Ctrl Z по кейсу HackAlem AI для ТОО «Электрокомплект». Ассистент помогает покупателю найти электротовары на ekt.kz, проверить характеристики и наличие, сравнить варианты, предварительно подобрать аналог и собрать корзину с явным подтверждением каждого изменения.
В текущей версии это витрина с ИИ-консультантом, пошаговым оформлением демо-заявки и инструментами для закупщика: фильтры каталога, избранное, история просмотров, разбор спецификаций, русский, казахский и английский интерфейс, пересчёт цен и выгрузка подборки в Excel/PDF. Покупатель может пройти путь от поиска товара до подборки и демо-заявки с контактами, адресом, желаемой датой доставки и способом оплаты.
Основной принцип: сведения о товаре берутся из каталога, а решение об изменении корзины остаётся за пользователем. Объяснение задачи — в CASE.md, подготовка выступления — в сценарии защиты.
Возможности и статус
| Возможность | Текущая реализация |
|---|---|
| Каталог | Поиск, фильтры, сравнение, избранное и история; снимок из 100 товаров |
| EKT AI | Генерация ответов и инструменты чтения каталога; требуется ключ провайдера |
| Корзина | Проверка живых цен и остатков, отдельное подтверждение изменений |
| Оформление | Контакты, доставка или самовывоз, адрес, дата, интервал, способ оплаты, история демо-заявок |
| Документы | Разбор спецификаций, экспорт подборки в XLSX/PDF, квитанция заявки в TXT |
| Языки | Русский, казахский и английский; цены отображаются в RUB/KZT/USD |
Заказ не отправляется в EKT, товар не резервируется, деньги не списываются. Интеграции с API заказов и платёжным сервисом пока нет.
Презентации и демонстрация
- Основная презентация HackAlem AI — задача, подход к решению и основные сценарии.
- Консультант для выбора электротоваров — характеристики, аналоги, подтверждение и корзина.
- Рабочее место закупщика — подборка, локализация, экспорт и предложения по развитию.
- HTML-демонстрация — подготовленный показ последовательности действий. Скачайте файл и откройте в браузере.
HTML-демонстрация показывает сценарий на сохранённых данных. Для работы с серверной сессией и живым API нужно запустить приложение. Презентации отражают разные этапы проекта; актуальные возможности описаны ниже.
Запуск
Нужен Node.js 24 и npm. В каталоге проекта:
npm ci
Скопируйте .env.example в .env.local и заполните выданные организатором EKT_API_USER, EKT_API_PASSWORD. Они используются только сервером. В архиве пароля нет. Без доступов EKT поиск по сохранённой выборке доступен, а добавление и изменение количества блокируются, поскольку проверить свежий остаток невозможно. Для просмотра каталога ключ ИИ не требуется. Для диалога с EKT AI обязательны серверные настройки LLM_URL, LLM_API_KEY и LLM_MODEL; без них чат показывает статус отключённого ИИ. Заполненный .env.local не нужно загружать в GitHub.
npm run build
node scripts/migrate-local.mjs
npm run dev
Откройте адрес, напечатанный сервером, обычно http://localhost:5173. Миграцию выполняйте один раз для новой локальной базы. Для локальной проверки собранного Worker используйте npm start и адрес из его вывода. Эта команда не публикует приложение. Локальная D1 хранится в .wrangler/state. Повторно запускать миграционный скрипт на уже созданной базе не требуется.
npm test
npm run test:currency
npm run test:exports
npm run test:ai
npm run test:checkout
npx tsc --noEmit
Эти проверки запускаются без работающего сервера. npm test проверяет логику корзины на контролируемых данных, test:currency — курсы, округление и языковые сценарии, test:exports — состав подборки и генерацию документов. test:ai проверяет адаптер на подставных ответах провайдера без платных запросов. test:checkout проверяет поля формы, наличие, цены, срок предложения и защиту от повторного создания заявки.
Для HTTP-проверок сначала запустите приложение и подготовьте D1:
npm run test:catalog
npm run test:workflows
node scripts/test-localization-export.mjs --http
node scripts/test-ai-consultant.mjs --http
node scripts/test-checkout.mjs --http
test:catalog проверяет и фильтры, и серверный /api/catalog, поэтому для завершения всей команды нужен сервер. Живые сценарии EKT запускаются отдельно:
npm run test:integration
node scripts/test-workflows.mjs --live
Для них нужны настроенные доступы EKT, доступный API и подходящие актуальные остатки. Тесты создают отдельные сессии демонстрационной корзины и не оформляют реальных заказов. HTTP-проверки используют http://localhost:5173; другой адрес задаётся переменной TEST_URL.
Архитектура
Интерфейс React → серверные маршруты Vinext/Cloudflare Worker → API ekt.kz + D1. Клиент не получает BasicAuth и не может самостоятельно задать цену. Данные каталога импортированы в data/catalog.json; lib/domain.ts отвечает за нормализацию, поиск, правила подбора и количества. app/api/assistant/route.ts обрабатывает диалог и двухэтапное добавление. lib/store.ts отвечает за работу с D1. lib/ai-consultant.ts реализует обращения к модели и инструменты чтения каталога, lib/ekt.ts — запрос актуальной карточки товара. Форма оформления находится в app/checkout.tsx, серверные правила — в lib/checkout.ts, маршрут — в app/api/checkout/route.ts.
Витрина и её фильтры находятся в app/storefront.tsx и lib/catalog-browser.ts. lib/workflows.ts описывает операции корзины, местные остатки и разбор спецификаций. lib/i18n.ts, lib/english.ts и lib/ai-copy.ts содержат переводы интерфейса и вспомогательную обработку поисковых запросов. lib/currency.ts и /api/rates отвечают за валютное отображение, а lib/selection.ts и lib/export-selection.ts — за состав и выгрузку подборки.
Публичный /api/catalog отдаёт снимок товаров, /api/assistant обслуживает диалог и действия текущей сессии, /api/attachment извлекает текст вложений, /api/selection возвращает данные для экспорта, /api/checkout проверяет и сохраняет демо-заявки текущей сессии. Учётные данные внешнего API не передаются браузеру.
Сессия идентифицируется случайной HttpOnly cookie с SameSite=Strict и Secure на HTTPS. Запросы изменения требуют совпадения Origin. Серверное предложение содержит ID товара, количество, цену, случайный токен и срок пять минут. Подтверждение повторно читает API, проверяет доступное количество вместе с уже добавленным. Изменившаяся цена требует нового согласия. Обновление строки D1 использует сравнение revision: конкурентные подтверждения не могут оба записать одну версию состояния.
Диалог, корзина, оценки и демо-заявки с контактами доступны в пределах 24-часовой сессии. Просроченные записи удаляются при создании новых сессий; отдельного планировщика очистки нет. Для настоящего магазина нужны его авторизация, согласованная политика хранения, лимиты на уровне инфраструктуры, мониторинг и нагрузочное тестирование.
Данные и достоверность
Выборка: 100 реальных карточек с первых пяти страниц, полученных 2026-09-23. В неё входят цены, остатки по складам, свойства, описания, URL и изображения. Публичные изображения загружаются напрямую с ekt.kz. Открытие карточки, сравнение, подготовка и подтверждение добавления запрашивают детали через /api/products/detail?id=.... При недоступности API карточка и сравнение могут показать отмеченный снимок, но добавление и изменение количества требуют успешной свежей проверки. Поиск остаётся по выборке, поэтому «не найден» не означает «нет в магазине». В API нет найденного товара — неизвестные значения не подменяются нулями.
Пересоздать выборку можно скриптом ниже, передав доступ через переменные окружения оболочки. CATALOG_PAGES по умолчанию равен 30; значение all обходит страницы до пустого ответа. CATALOG_MAX_PRODUCTS ограничивает размер (по умолчанию 10000). Скрипт последовательно перебирает страницы и загружает карточки с параллелизмом четыре.
node --env-file=.env.local scripts/sync-catalog.mjs
Команда выше загружает переменные из .env.local. Параметр --resume продолжает сохранённый прогресс. Есть повторные попытки, тайм-ауты и защита от повторяющихся страниц. При ошибке прежний каталог сохраняется; новый файл заменяется атомарно. Ограничение встроенного снимка — 12 МБ, для большего каталога нужен индекс в базе. После обновления пересоберите приложение. Автоматическое расписание не настроено. В переданной версии снимок содержит 100 товаров. Число товаров и дату загрузки нужно проверять в data/catalog.json: настройки загрузчика сами по себе не означают, что весь каталог уже получен.
Подбор аналога требует совпадения группы каталога и минимум двух известных критических параметров; несовпадающий известный параметр исключает кандидата. Отсутствие противоречий не доказывает совместимость. Полная электробезопасность требует инженерной проверки. При противоречии номинала между названием и полями автоматические аналоги не выдаются.
ИИ не должен придумывать условия покупки. Реальные сроки, тарифы доставки, адрес самовывоза и доступность способов оплаты требуют подтверждения менеджером; выбранные в демо-форме значения являются пожеланиями покупателя. Сертификаты не выдумываются: при отсутствии ссылки в API пользователь направляется к менеджеру.
Подключение EKT AI
Сценарный обработчик диалога заменён генерацией ответов через модель. Задайте в серверном окружении:
LLM_URL=https://your-provider.example/v1/chat/completions
LLM_API_KEY=your-server-secret
LLM_MODEL=your-supported-model
Нужен полный HTTPS endpoint, совместимый с Chat Completions, function tools и параметром max_completion_tokens. Ключ не передаётся браузеру и не хранится в Git. После изменения настроек перезапустите приложение.
Без настроек чат показывает статус отключённого ИИ; прежние шаблонные консультации не включаются. Поиск через каталог, карточки, корзина и её подтверждения продолжают работать при доступности нужных данных.
Модель получает последние 8 сообщений, текущий вопрос, город, выбранный товар, ID и количества корзины и ограниченные данные каталога. Инструменты search_catalog и product_details только читают данные. ИИ не может менять корзину или оформлять заказ: покупатель использует карточку товара и отдельное подтверждение. Ответ формируется на языке интерфейса. При сбое провайдера показывается ошибка, историю и корзину не подменяют выдуманным результатом.
Ограничения адаптера: до 4 обращений к модели, до 4 инструментов за шаг и общий сигнал тайм-аута запросов модели 45 секунд. Качество ответов конкретного провайдера нужно проверить отдельно. Реальная генерация без ключа не проверена; автоматические тесты используют подставные ответы.
Для JPEG дополнительно нужна поддержка image_url с data URL. Сообщения и распознаваемые фотографии передаются настроенному провайдеру; контакты и адрес из формы заказа в историю ИИ не попадают. Не отправляйте платёжные данные в чат.
Вложения
До 4 МБ: DOCX, XLSX, текстовый PDF до 25 страниц, TXT, CSV; JPEG после подключения модели. DOCX/XLSX разбираются как ограниченный ZIP/XML без выполнения макросов, формул и инструкций. Старые бинарные .doc/.xls не поддерживаются: сохраните как DOCX/XLSX. PDF-сканы без текстового слоя автоматически не распознаются: можно ввести артикул вручную или подготовить JPEG для подключённой модели. Распознанный текст ограничен 12000 символами. Исходные файлы не сохраняются как отдельные вложения; извлечённый текст открывается в таблице спецификации (до 60 непустых строк). Пользователь проверяет артикул, соответствие товара и количество; неоднозначные позиции требуют ручного выбора. До 20 выбранных строк товаров можно добавить одним подтверждением после проверки API. Повторы одного товара объединяются по ID, а количества суммируются. Пример формата: 200300285_;2; файл — public/example-spec.csv. Последний разбор строк хранится в сессии для обращения менеджеру и экспорта. Загрузка и разбор файла сами по себе не меняют корзину.
Границы прототипа
- Корзина собственная, не интегрирована в ekt.kz: предоставлены только методы чтения товаров. Ссылка
/#cartоткрывает актуальную демонстрационную корзину той же сессии. Нет оплаты, реального заказа или резервирования. - Работа модели и распознавание JPEG требуют настройки провайдера. Без неё ИИ-чат отключён, а каталог остаётся доступным.
- Есть адаптивная страница и виджет
/widget-demo. На реальный сайт он пока не установлен. - Сертификат выводится только при наличии данных. Производственные правила доставки, кратности и допустимых складов нужно согласовать с владельцем каталога.
- Валютный пересчёт предназначен для отображения. Исходные цены и серверные проверки остаются в KZT; оплата в RUB/USD не реализована.
- Избранное хранится в браузере, а диалог, оценки и корзина ограничены сроком сессии. Постоянного личного кабинета, совместных подборок и общей аналитической панели пока нет.
- Автоматические тесты покрывают основной цикл корзины, но не являются аудитом безопасности и нагрузочным испытанием.
Проверяемые сценарии
Тесты проверяют поиск по артикулу, противоречивые характеристики, количество и остаток, явное подтверждение, отмену, конкурентную запись, сохранение корзины, изоляцию сессий и отклонение чужого Origin. Отдельные наборы покрывают ИИ-инструменты, оформление заявки, валюты и экспорт. Проверки вспомогательных функций прежнего диалога не означают, что сценарный чат по-прежнему используется.
Фронтенд предоставляет WebMCP search_catalog только для поиска: инструмент не меняет корзину.
Диалог и карточки
История до 60 сообщений и последняя выдача восстанавливаются с сервера в пределах 24-часовой сессии. Модель использует последние 8 сообщений для контекста. Уточнения обрабатываются подключённым ИИ; фразы в чате сами по себе не дают модели права менять корзину. При ошибке отправки вопрос возвращается в поле ввода.
Предупреждения о противоречивых характеристиках видны в карточках и перед подтверждением. Ссылки на сертификаты извлекаются только из соответствующих полей и только с HTTPS-доменов EKT; фотография товара не считается сертификатом. Отсутствие конфликтов характеристик не гарантирует безопасную замену.
Обновлённый интерфейс
На широком экране чат и каталог видны рядом. В узком окне используются вкладки «Диалог» и «Товары» со счётчиком результатов. На компьютере доступно «Развернуть чат», чтобы сосредоточиться на диалоге. Добавление открывает выбор количества, а затем отдельную панель подтверждения. Карточки выделяют производителя, стоимость за единицу и наличие; служебные детали остаются в раскрываемой карточке. Загрузка файла находится на панели ввода. Пустая выдача сопровождается пояснением и кнопкой возврата к диалогу.
У товара доступны «О товаре» и «Добавить». Панель количества показывает остаток в выбранном городе, уже добавленные единицы, кратность и предварительную сумму. После «Проверить и добавить» сервер готовит предложение. Только отдельное подтверждение записывает изменение. При успехе появляется уведомление «Корзина обновлена» с переходом к её содержимому.
Новые сценарии
- Выбор города показывает местные остатки; Астана учитывает склад «Нур-Султан». Изменение города отменяет ожидающее подтверждение, но само по себе не меняет корзину.
- Сравнение 2–3 товаров: цена, местный остаток, характеристики и выделение различий. Если API недоступен, таблица и карточка показывают сохранённые данные с предупреждением и датой. Для добавления и изменения количества нужна успешная актуальная проверка.
- Изменение количества и удаление из корзины требуют отдельного подтверждения. Пакетное добавление выполняется целиком либо не выполняется; повторы одного товара объединяются, количества суммируются. Изменение цены требует нового согласия.
- «Вопрос менеджеру» собирает редактируемый текст из города, корзины, истории и последнего разбора спецификации. Его можно скачать; автоматической отправки нет.
Виджет
Демонстрация: /widget-demo; компактный интерфейс: /widget. Подключение на том же домене:
<script src="/widget.js" defer></script>
При reverse proxy нужно направить /widget, /widget.js, /api/assistant, /api/attachment, /api/selection, /api/checkout, /api/rates, ресурсы приложения и шрифт /fonts/DejaVuSans.ttf на этот сервис. Для полной витрины нужен также /api/catalog. Маршруты нужно согласовать с существующим сайтом. Скрипт использует Shadow DOM для оболочки и iframe для приложения. При подключении с другого домена кнопка открывает консультанта в отдельной вкладке: это сохраняет работу сессии без ослабления cookie-защиты. Реальная корзина EKT требует отдельной интеграции. Внешняя оболочка виджета содержит русские и казахские подписи; сам консультант поддерживает также английский.
Витрина и каталог
Главная страница объединяет категории, бренды, товарные карточки, подборки и ответы на частые вопросы. Каталог доступен по /#catalog, избранное — /#favorites, консультант — /#assistant, корзина текущей сессии — /#cart.
Покупатель может искать по артикулу и названию, выбирать категорию и производителя, задавать диапазон цены и номинальный ток, оставлять только товары с местным остатком. Доступны сортировка и страницы по 12 товаров. Пошаговый подбор предлагает выбрать известные параметры и применяет те же фильтры. Категории вычисляются по разделам исходных ссылок EKT.
Избранное сохраняется в текущем браузере и обновляется между его вкладками. История хранит последние 8 просмотренных товаров, из которых блок «Вы недавно смотрели» показывает до 4. Эти данные не синхронизируются между устройствами. Карточки витрины используют датированный снимок; открытие подробностей запрашивает API.
Русский, казахский и английский
Переключатель «Рус / Қаз / Eng» меняет интерфейс, подписи экспорта и сообщения проверки; форма оформления также переведена. Выбор хранится в браузере и синхронизируется между вкладками. Названия, описания и характеристики товаров остаются на языке исходного каталога.
Подключённая модель получает инструкцию отвечать на выбранном языке. Без модели диалог недоступен; поиск по каталогу работает отдельно. Изменения корзины подтверждаются через интерфейс, а не обещаниями модели в тексте ответа.
Валюты и курс
Язык связан с валютой отображения: «Рус» показывает RUB, «Қаз» — KZT, «Eng» — USD. Независимого переключателя валюты пока нет. Исходные цены и серверная проверка корзины всегда остаются в тенге.
/api/rates запрашивает датированный XML Национального банка Казахстана на текущую дату по времени Asia/Almaty. Проверяются дата ответа, положительные значения USD/RUB и количество единиц валюты. Интерфейс показывает источник и дату курса, поэтому пользователь видит, на каких данных основан пересчёт.
Браузер обновляет запрос при открытии, каждые 5 минут и при возврате фокуса окна. Сервер хранит успешный ответ в памяти и обычно обновляет его раз в час, если дата не изменилась. При сбое остаётся последнее доступное значение с предупреждением. После перезапуска используется резервный снимок из lib/currency.ts, датированный 23.09.2026; постоянного хранилища курсов нет.
Карточки, сравнение, корзина и Excel/PDF используют общую логику пересчёта. Цена единицы округляется до двух знаков, затем умножается на количество. Фильтр цены учитывает выбранную валюту, а при смене языка его границы очищаются. Пересчёт помогает сравнивать суммы и не означает, что магазин принимает оплату в выбранной валюте.
Оценка ответов
Под ответами ассистента есть «Помогло / Не помогло». Оценка привязана к стабильному ID ответа, хранится в текущей серверной сессии и восстанавливается после перезагрузки. Повторное нажатие снимает оценку, противоположное заменяет её.
Оценить чужой ответ или сообщение покупателя нельзя. Данные живут вместе с историей до 24 часов. В текущей версии реализован сбор оценки конкретного ответа; общей статистики качества и панели аналитики пока нет.
Excel и PDF
Кнопки экспорта доступны в панели инструментов консультанта и в корзине. Выгружаются подтверждённые позиции: артикул, исходное название, количество, сохранённая цена, сумма, город и ссылка на товар. Подписи соответствуют выбранному языку, цены — его валюте. Для RUB/USD в документе указывается дата и значение курса.
Экспорт не обновляет цену через EKT API, не подтверждает ожидающее действие и не создаёт заказ. Для пересчёта сохранённой цены KZT используется курс, доступный интерфейсу при выгрузке. Файл не является счётом и не подтверждает резервирование.
Отдельный блок содержит строки последней спецификации, которые ещё не покрыты количеством в корзине. Эти строки не входят в итог. Если спецификацию меняли только на экране, сначала повторите разбор, чтобы обновить серверные данные для выгрузки.
Excel создаётся как настоящий OOXML .xlsx: артикулы записываются текстом с сохранением ведущих нулей, количество и деньги — числами, суммы строк и итог — формулами с сохранёнными результатами. Пользовательский текст не исполняется как формула.
PDF создаётся в браузере со встроенным DejaVu Sans, переносами строк, ссылками и нумерацией страниц. Поддерживаются кириллица и казахские буквы. Лицензия шрифта находится в public/fonts/LICENSE-DejaVu.txt. Генерация документов не использует сторонний сервис.
Проверка текущей версии
В репозитории предусмотрены проверки логики корзины, валют, локализации, витрины, документов и HTTP-сценариев. Команды и условия запуска приведены в разделе «Запуск». Результаты предыдущей сборки не гарантируют успешную проверку после новых изменений: перед защитой тесты нужно запускать на той версии, которую показываете.
test:currency проверяет дату и единицы курса, отклонение некорректных значений, округление, английский поиск и фильтр цены в выбранной валюте. test:exports проверяет RU/KK/EN, числовые значения и формулы XLSX, текстовые артикулы, защиту от исполнения пользовательских формул и создание PDF. Образцы сохраняются в .sites-runtime/export-tests/.
HTTP-проверки охватывают восстановление сессии, оценки и их изоляцию, спецификации, сравнение и черновик менеджеру. Сценарии с живым EKT дополнительно проверяют добавление, изменение количества и удаление через отдельное подтверждение. Изменение актуальных остатков или исходных характеристик может потребовать пересмотра ожидаемых значений тестов.
Что показать на защите
- Витрина, фильтры и поиск по артикулу; при подключённой модели — уточнение параметров в чате.
- Характеристики, остатки в городе, предупреждение о противоречиях и обоснование предварительного аналога.
- Ссылка на исходную карточку и сертификат, если данные действительно содержат документ.
- Выбор количества, подготовка предложения и отмена без изменения корзины.
- Повторное действие с явным подтверждением, открытие корзины и отказ при превышении остатка.
- Сравнение товаров, избранное и разбор спецификации с ручной проверкой строк.
- Переключение «Рус / Қаз / Eng», изменение валюты и дата курса.
- Выгрузка Excel/PDF, итоговая сумма и отдельные позиции для уточнения.
- При подключённой модели — оценка ответа; восстановление сессии, черновик менеджеру и виджет.
- Корзина → «Оформить заказ»: контакты, адрес, желаемая дата и интервал, проверка суммы, подтверждение демо-заявки, её номер и скачивание квитанции.
Успешное добавление показывайте при работающем API. Если внешний сервис недоступен, объясните режим сохранённых данных и используйте HTML-сценарий как резервную демонстрацию. Не выдавайте его за живую проверку.
Оформление демонстрационной заявки
Кнопка «Оформить заказ» в корзине открывает контакты (фамилия, имя, необязательное отчество/email, телефон), курьера или самовывоз, город/адрес, желаемую дату и интервал, способ оплаты и комментарий. Дата выбирается с завтра на 30 дней вперёд по времени Казахстана; интервалы не являются бронированием. Адрес пункта самовывоза и стоимость доставки требуют согласования.
POST /api/checkout сначала создаёт пятиминутное предложение с проверенными ценами и наличием в выбранном городе, затем отдельно подтверждает его. Изменение корзины или цены требует повторной проверки. Токен защищает от повторного создания заявки. Данные формы разрешены по белому списку; номер карты/CVV не сохраняются. Контакты и адрес не попадают в историю ИИ. До 5 заявок доступны только своей HttpOnly-сессии до её истечения (24 часа); GET защищён сессией, запись — Origin и CAS revision. Заявку можно скачать как TXT.
Статус DEMO означает: не отправлено в EKT, не оплачено, товар не зарезервирован. Корзина сохраняется. «Картой при получении», «наличными», «счёт» — пожелания, а не гарантированные условия. Онлайн-эквайринг, реальный API заказов и бронирование доставки не подключены. Для приёма карты нужен hosted checkout платёжного провайдера и подтверждение оплаты через серверный webhook; поля PAN/CVV в приложении отсутствуют.
Проверки: npm run test:checkout и node scripts/test-checkout.mjs --http.
Если что-то не работает
Если корзина недоступна, проверьте первую сборку, миграцию D1 и привязку DB. Если отсутствует dist/server/wrangler.json, сначала выполните npm run build.
Если товары находятся, но не добавляются, проверьте доступы EKT_API_USER и EKT_API_PASSWORD, соединение с API, местный остаток и кратность. Снимок позволяет искать без живого каталога, но не заменяет проверку перед добавлением. После изменения настроек перезапустите приложение.
Если ИИ отключён, заполните все три переменные LLM_URL, LLM_API_KEY и LLM_MODEL. При ошибке провайдера проверьте его доступность, формат endpoint и поддержку function calling. Старый шаблонный чат как запасной режим не используется.
Если заявка не подтверждается, завершите или отмените ожидающее изменение корзины, проверьте контакты и дату, затем повторите проверку цен. Предложение действует 5 минут; изменение корзины, цены или остатка может потребовать нового предложения.
Если цена показывается в рублях, выбран русский интерфейс. Для отображения тенге переключитесь на «Қаз». При предупреждении о курсе учитывайте дату последнего доступного значения.
Если экспорт пустой, подтвердите товары в корзине или разберите спецификацию. Ожидающее предложение ещё не входит в подборку. Если файл не читается, проверьте формат, размер и наличие текстового слоя в PDF.
Если HTTP-тест не соединяется с приложением, запустите сервер и задайте правильный TEST_URL. Сообщение об истёкшей сессии или конфликте записи требует обновить страницу, проверить текущее состояние и подготовить действие заново.
Дальнейшее развитие
Для внедрения нужны API реальных заказов, платёжный сервис с серверным подтверждением оплаты, расчёт доставки и бронирование интервалов, интеграция с реальной корзиной и сессией ekt.kz, расширение и регулярное обновление каталога, согласованные правила совместимости, доступ к сертификатам и проверенный провайдер модели. Отдельно требуется согласовать хранение данных и проверить нагрузку.
Перспективные дополнения — постоянные подборки по объектам, совместное согласование списка, история изменений и аналитика оценок. В текущей версии этих возможностей нет. На пилоте можно измерять время до готовой подборки, долю завершённых без менеджера заданий, ошибки подбора и оценки ответов. Бизнес-эффект пока не измерен.
Авторы коммитов
История коммитов
- 2026-09-23 17:52Merge pull request #3 from BAITC-Hacks/feature/demo-checkoutDizzDer
- 2026-09-23 17:52Update README for current AI consultant and checkoutDizzDer
- 2026-09-23 17:44Add demo checkout with delivery, contacts and verified order confirmationDizzDer
- 2026-09-23 17:29Merge pull request #2 from BAITC-Hacks/feature/ekt-ai-consultantDizzDer
- 2026-09-23 17:25Merge latest README changes and retain AI setup documentationDizzDer
- 2026-09-23 17:23Replace scripted replies with EKT AI consultant and catalog toolsDizzDer
- 2026-09-23 17:18Update README.mdbahtiarabuzar
- 2026-09-23 17:14Fix quick-add request races and refresh quantity constraintsDizzDer
Все коммиты (18)
- 2026-09-23 17:11Update README.mdbahtiarabuzar
- 2026-09-23 17:01Improve cart flow, expand assistant and add English with daily currency rateszhasik6767
- 2026-09-23 16:27Add files via uploadbahtiarabuzar
- 2026-09-23 16:18Add files via uploadbahtiarabuzar
- 2026-09-23 16:10Update assistant with storefront, bilingual UI and selection exportsDizzDer
- 2026-09-23 15:22Replace presentation with latest EKT Assist defense deckzhasik6767
- 2026-09-23 15:20Add files via uploadbahtiarabuzar
- 2026-09-23 15:15Update EKT assistant with comparison, city selection, batch cart and widgetDizzDer
- 2026-09-23 14:29Add HackAlem AI presentation and README linkzhasik6767
- 2026-09-23 14:18Import EKT catalog assistant prototypeDizzDer
Структура репозитория (158 файлов)
.env.example .gitignore .npmrc .openai/hosting.json CASE.md EKT-demo.html EKT_HackAlem_AI_Charts_Photos.pptx EKT_Procurement_Studio_20.pptx EKT_REIMAGINED_22.pptx README.md app/api/assistant/route.ts app/api/attachment/route.ts app/api/catalog/route.ts app/api/checkout/route.ts app/api/rates/route.ts app/api/selection/route.ts app/chatgpt-auth.ts app/checkout.css app/checkout.tsx app/currency-context.tsx app/features.css app/features.tsx app/globals.css app/layout.tsx app/locale.tsx app/page.tsx app/product.css app/redesign.css app/selection.tsx app/shopping.css app/storefront.css app/storefront.tsx app/widget-demo/page.tsx app/widget/page.tsx cloudflare-env.d.ts components.json components/ui/accordion.tsx components/ui/alert-dialog.tsx components/ui/alert.tsx components/ui/aspect-ratio.tsx components/ui/attachment.tsx components/ui/avatar.tsx components/ui/badge.tsx components/ui/breadcrumb.tsx components/ui/bubble.tsx components/ui/button-group.tsx components/ui/button.tsx components/ui/calendar.tsx components/ui/card.tsx components/ui/carousel.tsx components/ui/chart.tsx components/ui/checkbox.tsx components/ui/collapsible.tsx components/ui/combobox.tsx components/ui/command.tsx components/ui/context-menu.tsx components/ui/dialog.tsx components/ui/direction.tsx components/ui/drawer.tsx components/ui/dropdown-menu.tsx components/ui/empty.tsx components/ui/field.tsx components/ui/form.tsx components/ui/hover-card.tsx components/ui/input-group.tsx components/ui/input-otp.tsx components/ui/input.tsx components/ui/item.tsx components/ui/kbd.tsx components/ui/label.tsx components/ui/marker.tsx components/ui/menubar.tsx components/ui/message-scroller.tsx components/ui/message.tsx components/ui/native-select.tsx components/ui/navigation-menu.tsx components/ui/pagination.tsx components/ui/popover.tsx components/ui/progress.tsx components/ui/radio-group.tsx components/ui/resizable.tsx components/ui/scroll-area.tsx components/ui/select.tsx components/ui/separator.tsx components/ui/sheet.tsx components/ui/sidebar.tsx components/ui/skeleton.tsx components/ui/slider.tsx components/ui/sonner.tsx components/ui/spinner.tsx components/ui/switch.tsx components/ui/table.tsx components/ui/tabs.tsx components/ui/textarea.tsx components/ui/toggle-group.tsx components/ui/toggle.tsx components/ui/tooltip.tsx data/catalog.json db/index.ts db/schema.ts drizzle.config.ts drizzle/0000_narrow_titanium_man.sql drizzle/meta/0000_snapshot.json drizzle/meta/_journal.json eslint.config.mjs examples/d1/app/api/notes/route.ts examples/d1/db/schema.ts hooks/use-mobile.ts lib/ai-consultant.ts lib/ai-copy.ts lib/catalog-browser.ts lib/checkout.ts lib/currency.ts lib/domain.ts lib/ekt.ts lib/english.ts lib/export-selection.ts lib/extract.ts lib/feedback.ts lib/i18n.ts lib/selection.ts lib/store.ts lib/utils.ts lib/workflows.ts next.config.ts package-lock.json package.json postcss.config.mjs public/example-spec.csv public/favicon.svg public/file.svg public/fonts/DejaVuSans.ttf public/fonts/LICENSE-DejaVu.txt public/globe.svg public/widget.js public/window.svg scripts/build-verified.sh scripts/execution-profile.mjs scripts/install-ci.mjs scripts/install-ci.sh scripts/install-pnpm.sh scripts/migrate-local.mjs scripts/npm-install.mjs scripts/pnpm-install.mjs scripts/run-framework.mjs scripts/sites-env.mjs scripts/sites-env.sh scripts/sync-catalog.mjs scripts/test-ai-consultant.mjs scripts/test-catalog-browser.mjs scripts/test-checkout.mjs scripts/test-currency.mjs scripts/test-localization-export.mjs scripts/test-workflows.mjs scripts/test.mjs tsconfig.json vite.config.ts Сценарий-защиты.md
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.