Files
QuoteForge/pricelists_window.md
2026-02-11 19:16:01 +03:00

14 KiB
Raw Blame History

Промпт для ИИ: Перенос паттерна Прайслист

Используй этот документ как промпт для ИИ при переносе реализации прайслиста в другой проект.


Задача

Я имею рабочую реализацию окна "Прайслист" в проекте 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 если не найден

Регистрация маршрутов:

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 (было):

func (h *PricelistHandler) List(c *gin.Context) {
    localPLs, err := h.localDB.GetLocalPricelists()
    // ...
}

Backend (стало):

func (h *CatalogHandler) List(c *gin.Context) {
    catalogs, err := h.service.GetAllCatalogs(page, perPage)
    // ...
}

Frontend (было):

const resp = await fetch(`/api/pricelists?page=${page}&per_page=20`);

Frontend (стало):

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