316 lines
14 KiB
Markdown
316 lines
14 KiB
Markdown
# Промпт для ИИ: Перенос паттерна Прайслист
|
||
|
||
Используй этот документ как промпт для ИИ при переносе реализации прайслиста в другой проект.
|
||
|
||
---
|
||
|
||
## Задача
|
||
|
||
Я имею рабочую реализацию окна "Прайслист" в проекте QuoteForge. Нужно перенести эту реализацию в проект [ДОП_ПРОЕКТ_НАЗВАНИЕ], сохраняя структуру, логику и UI/UX.
|
||
|
||
## Что перенести
|
||
|
||
### Frontend - Лист прайслистов (`/pricelists`)
|
||
|
||
**Файл источник:** QuoteForge/web/templates/pricelists.html
|
||
|
||
**Компоненты:**
|
||
1. **Таблица** - список прайслистов с колонками:
|
||
- Версия (монофонт)
|
||
- Тип (estimate/warehouse/competitor)
|
||
- Дата создания
|
||
- Автор (обычно "sync")
|
||
- Позиций (количество товаров)
|
||
- Исп. (использований)
|
||
- Статус (зеленый "Активен" / серый "Неактивен")
|
||
- Действия (Просмотр, Удалить если не используется)
|
||
|
||
2. **Пагинация** - навигация по страницам с активной страницей выделена
|
||
|
||
3. **Модальное окно** - "Создать прайслист" (если есть прав на запись)
|
||
|
||
**Что копировать:**
|
||
- HTML структуру таблицы из lines 10-30
|
||
- JavaScript функции:
|
||
- `loadPricelists(page)` - загрузка списка
|
||
- `renderPricelists(items)` - рендер таблицы
|
||
- `renderPagination(total, page, perPage)` - пагинация
|
||
- `checkPricelistWritePermission()` - проверка прав
|
||
- Модальные функции: `openCreateModal()`, `closeCreateModal()`, `createPricelist()`
|
||
- CSS классы Tailwind (скопируются как есть)
|
||
|
||
**Где использовать в дочернем проекте:**
|
||
- URL: `/pricelists` (или адаптировать под ваши маршруты)
|
||
- API: `GET /api/pricelists?page=1&per_page=20`
|
||
|
||
---
|
||
|
||
### Frontend - Детали прайслиста (`/pricelists/:id`)
|
||
|
||
**Файл источник:** QuoteForge/web/templates/pricelist_detail.html
|
||
|
||
**Компоненты:**
|
||
1. **Хлебная крошка** - кнопка назад на список
|
||
|
||
2. **Инфо-панель** - сводка по прайслисту:
|
||
- Версия (монофонт)
|
||
- Дата создания
|
||
- Автор
|
||
- Позиций (количество)
|
||
- Использований (в скольких конфигах)
|
||
- Статус (зеленый/серый)
|
||
- Истекает (дата или "-")
|
||
|
||
3. **Таблица товаров** - с поиском и пагинацией:
|
||
- Артикул (монофонт, lot_name)
|
||
- Категория (извлекается первая часть до "_")
|
||
- Описание (обрезается до 60 символов с "...")
|
||
- [УСЛОВНО] Доступно (qty) - только для warehouse источника
|
||
- [УСЛОВНО] Partnumbers - только для warehouse источника
|
||
- Цена, $ (с 2 знаками после запятой)
|
||
- Настройки (аббревиатуры: РУЧН, Сред, Взвеш.мед, периоды (1н, 1м, 3м, 1г), коэффициент, МЕТА)
|
||
|
||
4. **Поиск** - дебаунс 300мс, поиск по lot_name
|
||
|
||
5. **Динамические колонки** - qty и partnumbers скрываются/показываются в зависимости от source (warehouse или нет)
|
||
|
||
**Что копировать:**
|
||
- HTML структуру из lines 4-78
|
||
- JavaScript функции:
|
||
- `loadPricelistInfo()` - загрузка деталей прайслиста
|
||
- `loadItems(page)` - загрузка товаров
|
||
- `renderItems(items)` - рендер таблицы товаров
|
||
- `renderItemsPagination(total, page, perPage)` - пагинация товаров
|
||
- `isWarehouseSource()` - проверка источника
|
||
- `toggleWarehouseColumns()` - показать/скрыть conditional колонки
|
||
- `formatQty(qty)` - форматирование количества
|
||
- `formatPriceSettings(item)` - форматирование строки настроек
|
||
- `escapeHtml(text)` - экранирование HTML
|
||
- Debounce для поиска (lines 300-306)
|
||
- CSS классы Tailwind
|
||
- Логику conditional колонок (lines 152-164)
|
||
|
||
**Где использовать в дочернем проекте:**
|
||
- URL: `/pricelists/:id`
|
||
- API:
|
||
- `GET /api/pricelists/:id`
|
||
- `GET /api/pricelists/:id/items?page=1&per_page=50&search=...`
|
||
|
||
---
|
||
|
||
### Backend - Handler
|
||
|
||
**Файл источник:** QuoteForge/internal/handlers/pricelist.go
|
||
|
||
**Методы для реализации:**
|
||
|
||
1. **List** (lines 23-89)
|
||
- Параметры: `page`, `per_page`, `source` (фильтр), `active_only`
|
||
- Логика:
|
||
- Получить все прайслисты
|
||
- Отфильтровать по source (case-insensitive)
|
||
- Отсортировать по CreatedAt DESC (свежее сверху)
|
||
- Пагинировать
|
||
- Для каждого: посчитать товары (CountLocalPricelistItems), использования (IsUsed)
|
||
- Вернуть JSON с полями: id, source, version, created_by, item_count, usage_count, is_active, created_at, synced_from
|
||
|
||
2. **Get** (lines 92-116)
|
||
- Параметр: `id` (uint из URL)
|
||
- Логика:
|
||
- Получить прайслист по ID
|
||
- Вернуть его детали (id, source, version, item_count, is_active, created_at)
|
||
- 404 если не найден
|
||
|
||
3. **GetItems** (lines 119-181)
|
||
- Параметры: `id` (URL), `page`, `per_page`, `search` (query)
|
||
- Логика:
|
||
- Получить прайслист по ID
|
||
- Получить товары этого прайслиста
|
||
- Фильтровать по lot_name LIKE search (если передан)
|
||
- Посчитать total
|
||
- Пагинировать
|
||
- Для каждого товара: извлечь категорию из lot_name (первая часть до "_")
|
||
- Вернуть JSON: source, items (id, lot_name, price, category, available_qty, partnumbers), total, page, per_page
|
||
|
||
4. **GetLotNames** (lines 183-211)
|
||
- Параметр: `id` (URL)
|
||
- Логика:
|
||
- Получить все lot_names из этого прайслиста
|
||
- Отсортировать alphabetically
|
||
- Вернуть JSON: lot_names (array of strings), total
|
||
|
||
5. **GetLatest** (lines 214-233)
|
||
- Параметр: `source` (query, default "estimate")
|
||
- Логика:
|
||
- Нормализовать source (case-insensitive)
|
||
- Получить самый свежий прайслист по этому source
|
||
- Вернуть его детали
|
||
- 404 если не найден
|
||
|
||
**Регистрация маршрутов:**
|
||
```go
|
||
pricelists := api.Group("/pricelists")
|
||
{
|
||
pricelists.GET("", handler.List)
|
||
pricelists.GET("/latest", handler.GetLatest)
|
||
pricelists.GET("/:id", handler.Get)
|
||
pricelists.GET("/:id/items", handler.GetItems)
|
||
pricelists.GET("/:id/lots", handler.GetLotNames)
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Адаптация для другого проекта
|
||
|
||
### Что нужно изменить
|
||
|
||
1. **Источник данных**
|
||
- QuoteForge использует local DB (LocalPricelist, LocalPricelistItem)
|
||
- В вашем проекте: замените на ваши структуры/таблицы
|
||
- Сущность "прайслист" может называться по-другому
|
||
|
||
2. **API маршруты**
|
||
- `/api/pricelists` → ваш путь
|
||
- `:id` - может быть UUID вместо int, адаптировать parsing
|
||
|
||
3. **Имена полей**
|
||
- Если у вас нет поля `version` - используйте ID или дату
|
||
- Если нет `source` - опустить фильтр
|
||
- Если нет `IsUsed` - считать как всегда 0
|
||
|
||
4. **Структуры данных**
|
||
- Pricelist должна иметь: id, name/version, created_at, source, item_count
|
||
- PricelistItem должна иметь: id, lot_name, price, available_qty, partnumbers
|
||
|
||
5. **Условные колонки**
|
||
- Логика: если source == "warehouse", показать qty и partnumbers
|
||
- Адаптировать под ваши источники/типы
|
||
|
||
### Что копировать как есть
|
||
|
||
- **HTML структура** - таблицы, модали, классы Tailwind
|
||
- **JavaScript логика** - все функции загрузки, рендера, пагинации
|
||
- **CSS классы** - Tailwind работает везде одинаково
|
||
- **Форматирование функций** - formatPrice, formatQty, formatDate
|
||
|
||
---
|
||
|
||
## Пошаговая инструкция для ИИ
|
||
|
||
1. **Прочитай оба файла:**
|
||
- QuoteForge/web/templates/pricelists.html (список)
|
||
- QuoteForge/web/templates/pricelist_detail.html (детали)
|
||
- QuoteForge/internal/handlers/pricelist.go (backend)
|
||
|
||
2. **Определи структуры данных в дочернем проекте:**
|
||
- Какая таблица хранит "прайслисты"?
|
||
- Какие у неё поля?
|
||
- Как связаны товары?
|
||
|
||
3. **Адаптируй Backend:**
|
||
- Скопируй методы Handler
|
||
- Замени DB вызовы на вызовы вашего хранилища
|
||
- Замени имена полей в JSON ответах если нужно
|
||
- Убедись, что API возвращает нужный формат
|
||
|
||
4. **Адаптируй Frontend - Список:**
|
||
- Скопируй HTML таблицу
|
||
- Скопируй функции load/render/pagination
|
||
- Замени маршруты `/pricelists` → ваши
|
||
- Замени API endpoint → ваш
|
||
- Протестируй список загружается
|
||
|
||
5. **Адаптируй Frontend - Детали:**
|
||
- Скопируй HTML для деталей
|
||
- Скопируй функции loadInfo/loadItems/render
|
||
- Замени маршруты и endpoints
|
||
- Особое внимание на conditional колонки (toggleWarehouseColumns)
|
||
- Протестируй поиск работает
|
||
|
||
6. **Протестируй:**
|
||
- Список загружается
|
||
- Пагинация работает
|
||
- Детали открываются
|
||
- Поиск работает
|
||
- Conditional колонки показываются/скрываются правильно
|
||
- Форматирование цен и дат работает
|
||
|
||
---
|
||
|
||
## Пример адаптации
|
||
|
||
### Backend (было):
|
||
```go
|
||
func (h *PricelistHandler) List(c *gin.Context) {
|
||
localPLs, err := h.localDB.GetLocalPricelists()
|
||
// ...
|
||
}
|
||
```
|
||
|
||
### Backend (стало):
|
||
```go
|
||
func (h *CatalogHandler) List(c *gin.Context) {
|
||
catalogs, err := h.service.GetAllCatalogs(page, perPage)
|
||
// ...
|
||
}
|
||
```
|
||
|
||
### Frontend (было):
|
||
```javascript
|
||
const resp = await fetch(`/api/pricelists?page=${page}&per_page=20`);
|
||
```
|
||
|
||
### Frontend (стало):
|
||
```javascript
|
||
const resp = await fetch(`/api/catalogs?page=${page}&per_page=20`);
|
||
```
|
||
|
||
---
|
||
|
||
## Качество результата
|
||
|
||
Когда закончишь:
|
||
- ✅ Список и детали выглядят идентично QuoteForge
|
||
- ✅ Все функции работают (load, render, pagination, search, conditional columns)
|
||
- ✅ Обработка ошибок (404, empty list, network errors)
|
||
- ✅ Таблицы с Tailwind классами оформлены одинаково
|
||
- ✅ Форматирование чисел/дат совпадает
|
||
|
||
---
|
||
|
||
## Вопросы для ИИ
|
||
|
||
Перед тем как давать этот промпт, ответь на эти вопросы:
|
||
|
||
1. **Какие у тебя структуры данных для "прайслиста"?**
|
||
- Пример: какие поля, как называется таблица
|
||
|
||
2. **Какие API endpoints уже есть?**
|
||
- Или нужно создать с нуля?
|
||
|
||
3. **Есть ли уже разница в источниках (estimate/warehouse)?**
|
||
- Или все одного типа?
|
||
|
||
4. **Нужна ли возможность создавать прайслисты?**
|
||
- Или только просмотр?
|
||
|
||
---
|
||
|
||
## Чеклист для проверки
|
||
|
||
После переноса проверь:
|
||
|
||
- [ ] Backend: List возвращает правильный JSON
|
||
- [ ] Backend: Get возвращает детали
|
||
- [ ] Backend: GetItems возвращает товары с поиском
|
||
- [ ] Frontend: Список загружается на `/pricelists`
|
||
- [ ] Frontend: Клик на прайслист открывает `/pricelists/:id`
|
||
- [ ] Frontend: Таблица на детальной странице рендеритсяся
|
||
- [ ] Frontend: Поиск работает с дебаунсом
|
||
- [ ] Frontend: Пагинация работает
|
||
- [ ] Frontend: Conditional колонки показываются/скрываются
|
||
- [ ] Frontend: Форматирование цен работает (2 знака)
|
||
- [ ] Frontend: Форматирование дат работает (ru-RU)
|
||
- [ ] UI: Выглядит идентично QuoteForge
|