Files
project-maps/KPgenerator/MAP.md
T

11 KiB
Raw Blame History

KPgenerator

Назначение

Генератор коммерческих предложений (КП) для МПО-Информ / servaki. Реализован не как обычное приложение, а как набор n8n-воркфлоу (http://192.168.1.158:5678, доступ через finik). Репозиторий хранит исходники Code-нод n8n (файлы build_*.js / prep_*.js), shell-воркеры на finik, парсер прайсов и документацию.

Возможности: чат-страница для сборки КП → запись в Postgres (таблица quotes), HTML-рендер КП с печатью, генерация PDF (wkhtmltopdf) в MinIO, история/поиск по КП, ИИ-подбор шаблона (Ollama qwen2.5:1.5b с откатом на regex-правила), прайс-лист (price_list, импорт/поиск), отправка КП в Telegram (sendDocument) и голосовые комментарии (Voicebox TTS → sendVoice). Секреты вырезаны (хранятся на Я.Диске).

  • Язык: JavaScript (тела n8n Code-нод) + Bash-воркеры + Python (парсер прайсов).
  • LOC (исходники): ~731 (JS ≈ 542, Bash ≈ 91, Python ≈ 78). Плюс не-код артефакты: README (~500 стр.), HTML-снапшот базы знаний, дубли zip.
  • Ключевые ID: воркфлоу «KP Dialog» JT6mVXd7LV8Dmuog, «Price List API» mxPgqVNbxALGrMYx, «KP CRUD» kpgencrud01; Postgres cred kpgenpg0001.

Архитектура

graph TD
  subgraph Client["Браузер / чат kp.servaki.online"]
    PAGE["prep_page.js — SPA-чат + Telegram-логин"]
    VIEW["build_view.js — HTML/PDF рендер КП"]
  end
  subgraph N8N["n8n .158 — воркфлоу KP Dialog / Price API"]
    CREATE["prep_create.js — создать КП"]
    HIST["prep_history.js — история/поиск"]
    TPL["build_templates.js — шаблоны КП"]
    AI["build_ai.js — ИИ-подбор шаблона"]
    SETPDF["prep_setpdf.js — запись pdf_url"]
    TG["build_tg.js / prep_tg.js — отправка в Telegram"]
    TGAUTH["build_tgauth.js — проверка Telegram-подписи"]
    VENQ["prep_voice_enq.js — очередь голоса"]
    VPEND["prep_voice_pending.js — выдача задач воркеру"]
    VDONE["prep_voice_done.js — отметка готово"]
  end
  subgraph DB["Postgres (.158)"]
    QUOTES[("quotes")]
    PRICE[("price_list")]
    VQ[("tg_voice_queue")]
  end
  subgraph Workers["finik — cron-воркеры"]
    PDFSH["kp-pdf.sh — wkhtmltopdf → MinIO"]
    VOICESH["kp-voice.sh — TTS → MinIO → sendVoice"]
  end
  IMP["catalog-source/import_prices.py — парсер xlsx"]
  MINIO["MinIO aimedia / s3.servaki.online"]
  OLLAMA["Ollama .158:11434"]
  VOICEBOX["Voicebox 89.125.89.16:5501"]
  TGAPI["api.telegram.org @servaki_online_bot"]

  PAGE --> CREATE --> QUOTES
  PAGE --> HIST --> QUOTES
  PAGE --> TPL
  PAGE --> AI --> OLLAMA
  PAGE --> VIEW
  PAGE --> TGAUTH --> TGAPI
  VIEW --> TG --> TGAPI
  VIEW --> VENQ --> VQ
  IMP --> PRICE
  PDFSH --> VIEW
  PDFSH --> MINIO
  PDFSH --> SETPDF --> QUOTES
  VOICESH --> VPEND --> VQ
  VOICESH --> VOICEBOX
  VOICESH --> MINIO
  VOICESH --> TGAPI
  VOICESH --> VDONE --> VQ

Entry-points / маршруты

База: http://192.168.1.158:5678/webhook. Price-эндпоинты защищены заголовком X-API-Key (иначе 403).

Метод Путь Исходник Назначение
GET /webhook/kp-chat prep_page.js Главная SPA-страница чата + Telegram-логин
POST /webhook/kp-chat/create prep_create.js Создать КП (INSERT в quotes)
GET /webhook/kp-chat/view?id=&pdf= build_view.js HTML/PDF-рендер КП (?pdf=1 — режим для wkhtmltopdf)
GET /webhook/kp-chat/history?q= prep_history.js История/поиск по quotes (ILIKE, LIMIT 50)
— (templates) build_templates.js Каталог шаблонов КП
POST /webhook/kp-chat/ai build_ai.js ИИ-подбор шаблона (Ollama + откат на правила)
POST /webhook/kp-chat/setpdf prep_setpdf.js UPDATE quotes.pdf_url (только эта колонка)
POST /webhook/kp-chat/telegram build_tg.js / prep_tg.js sendDocument/sendMessage КП в Telegram
POST /webhook/kp-chat/tg-auth build_tgauth.js Проверка Telegram-подписи (чистый JS SHA-256/HMAC)
POST /webhook/kp-chat/voice prep_voice_enq.js Enqueue голосового комментария (tg_voice_queue)
GET /webhook/kp-chat/voice-pending?key= prep_voice_pending.js Выдача задач воркеру (key-protected)
POST /webhook/kp-chat/voice-done prep_voice_done.js Отметка задачи выполненной
GET /webhook/kp (n8n нода) Список КП (используется kp-pdf.sh)
GET /webhook/price/init (Price API) Создать таблицу price_list (идемпотентно)
POST /webhook/price/import (Price API) UPSERT позиций прайса
GET /webhook/price/search?q=&category= (Price API) Поиск позиций (LIMIT 50)
PUT /api/v1/workflows/JT6mVXd7LV8Dmuog n8n API Деплой/откат воркфлоу из бэкапа

Ключевые цепочки вызовов

  1. Ручная сборка КП: /kp-chat (prep_page) → правка позиций → POST /kp-chat/create (prep_create → INSERT quotes) → GET /kp-chat/view?id= (build_view) → кнопка «Печать».
  2. *PDF-пайплайн (cron /5 на finik): kp-pdf.sh берёт GET /webhook/kp → для КП без pdf_url wkhtmltopdf '<view>?pdf=1' → mc cp в MinIO aimedia/kp/ → POST /kp-chat/setpdf {id,pdf_url} → публичная ссылка s3.servaki.online:8443/aimedia/kp/....
  3. ИИ-подбор: POST /kp-chat/ai {text} (build_ai) → regex-правила (база) + попытка Ollama qwen2.5:1.5b на .158:11434 (извлекает объект) → при таймауте/ошибке автооткат на правила → загрузка шаблона в чат.
  4. Отправка в Telegram: кнопка «В Telegram» (build_view) → POST /kp-chat/telegram {id,chat_id} (build_tg) → sendDocument PDF из MinIO через @servaki_online_bot (chat_id из Telegram-логина, tg-auth → build_tgauth).
  5. Голосовой комментарий (cron * на finik): кнопка «Голосом» → POST /kp-chat/voice (enq → tg_voice_queue) → kp-voice.sh: GET /voice-pending?key= → Voicebox TTS (89.125.89.16) → mc cp opus в MinIO → sendVoice по URL → POST /voice-done.
  6. Импорт прайса: catalog-source/import_prices.py парсит .xlsx (openpyxl) → _catalog_import.json → POST /webhook/price/import (через finik).

Тех-долг

Пометка: всё ниже — предположение по грепу/структуре; точность — через codebase-memory-mcp.

  • Дубли-артефакты (dead): zi2jSxII (56622 б = байт-в-байт kpgen-full.zip) и ziB7i0OA (55738 б = kpgen-full-project.zip) — безымянные копии архивов, кандидаты на удаление. Плюс три zip (KP_Generator_MPOall.zip, kpgen-full.zip, kpgen-full-project.zip) — снапшоты, не участвуют в рантайме.
  • Не-код в репо: KP-knowledge-base-2026-06-27.html — статический снапшот базы знаний (документация, не исполняется).
  • build_templates.js — не найдено явного webhook-роута в коде/README (шаблоны, вероятно, отдаются из prep_page или отдельной ноды); проверить, живой ли (ПРЕДПОЛОЖЕНИЕ).
  • Токены/секреты зашиты в build_tg.js (санитизированы в Gitea) — риск рассинхрона с Я.Диском.
  • Хрупкость деплоя: правка нод n8n только base64/quoted-heredoc (bash раскрывает ${...}/$json); нет CI — откат вручную через PUT /api/v1/workflows.
  • Общий прод-бот @servaki_online_bot делится с ТИНКО-парсером на Proxmox — трогать webhook/getUpdates нельзя (жёсткая внешняя связанность).
  • finik — шлюз к n8n .158, хост cron-воркеров (kp-pdf.sh, kp-voice.sh), Caddy для публичных ссылок (kp-pdf.sh, kp-voice.sh, import_prices.py, README).
  • vm-mts / .158 — 192.168.1.158: n8n :5678, Postgres, Ollama :11434 (build_ai.js, kp-pdf.sh, kp-voice.sh).
  • s3.servaki.online / MinIO aimedia — хранилище PDF и voice-ogg (kp-pdf.sh, kp-voice.sh).
  • kp.servaki.online — домен чата (Telegram /setdomain).
  • Telegram @servaki_online_bot (id 8142796440) — общий прод-бот, только исходящие (build_tg.js, kp-voice.sh, build_tgauth.js).
  • Voicebox/Piper 89.125.89.16:5501 — TTS (kp-voice.sh).
  • Внешние: Ollama, api.telegram.org, прайсы Wirenboard/ТИНКО. Ссылок на другие наши репо из списка (agent-sync, Heritage, egorin, orbit-bot и т.д.) — не обнаружено.

TODO для Лилии (codebase-memory-mcp)

  • Точный call-graph: воркфлоу собран из n8n-нод — граф связей восстановлен по README/грепу, а не из JSON воркфлоу. Дообогатить из экспортов JT6mVXd7LV8Dmuog / mxPgqVNbxALGrMYx (реальные связи WH→Prep→PG→Build→Resp).
  • Dead-code: подтвердить, что zi2jSxII/ziB7i0OA = дубли zip и удалимы; проверить живость build_templates.js (есть ли входящий роут).
  • Cross-service: зафиксировать рёбра KPgenerator → finik / .158 / MinIO / Voicebox / Telegram; свести с картами servaki-infra и orbit-bot (общий бот).
  • Секреты: сверить санитизированные build_tg.js / voice-скрипты с полной версией на Я.Диске.
  • Снапшот graph.db.zst: сохранить call-graph + маршруты + cross-service рёбра для инкрементального обновления при правке нод.