DoSoapCalc/docs/KNOWLEDGE_BASE.md

9.6 KiB
Raw Blame History

База знаний проекта DoSoap

Назначение проекта

DoSoap - это веб-приложение для расчета себестоимости продукции ручной работы. Пользователи могут:

  1. Выбрать калькулятор (мыло, свечи и т.д.)
  2. Ввести параметры продукта
  3. Получить автоматический расчет себестоимости
  4. Отправить результат в Telegram-бота

Архитектура системы

Frontend (Next.js)

Структура:

frontend/
  app/                    # Next.js App Router
    page.tsx              # Главная страница с меню
    layout.tsx            # Общий layout
  calculators/            # Модули калькуляторов
    soap/                 # Калькулятор мыла
      config.ts           # Конфигурация
      calc.ts             # Функции расчета
    candles/              # Калькулятор свечей
      config.ts
      calc.ts
  components/             # React компоненты
    CalculatorEngine.tsx  # Универсальный движок
    CalculatorMenu.tsx    # Меню выбора
  lib/                     # Утилиты и типы
    calculator-types.ts   # TypeScript типы
    calculator-registry.ts # Реестр калькуляторов
  docs/                    # Документация
    calculator-creation-guide.md

Технологии:

  • Next.js 15.3.3 с App Router
  • React 19
  • TypeScript 5
  • Tailwind CSS 4
  • Статический экспорт (output: 'export')

Backend (Express + Telegram)

Файлы:

  • backend/bot.js - основной файл бэкенда

Функционал:

  • Обработка POST запросов от фронтенда
  • Интеграция с Telegram Bot API
  • Загрузка и отправка фотографий
  • Форматирование сообщений для Telegram

API:

  • POST /api/submit - принимает данные расчета и отправляет в Telegram
  • Команда /myid - возвращает chat_id пользователя

Типы данных

FieldConfig

Определяет поле ввода в калькуляторе:

{
  id: string;              // Уникальный ID
  type: 'text' | 'number' | 'file';
  label: string;           // Название поля
  defaultValue?: string;
  gridCols?: 1 | 2;        // Ширина в grid
  required?: boolean;
  accept?: string;         // Для файлов
  groupName?: string;     // Группа для группировки
  showStepAfter?: string; // ID расчета после группы
}

CalculationStep

Шаг расчета (например, "Себестоимость основы"):

{
  id: string;
  name: string;
  formula: (values: Record<string, number>) => number;
  formulaDescription?: string;
}

SubtotalConfig

Подитог (например, "Итого себестоимость"):

{
  id: string;
  name: string;
  formula: (values, steps) => number;
  highlight?: boolean;     // Выделить визуально
  formulaDescription?: string;
}

AdditionalCalculation

Дополнительный расчет (например, "Цена за 100г"):

{
  id: string;
  name: string;
  formula: (values, steps, subtotals, additional?) => number;
  formulaDescription?: string;
}

Поток работы калькулятора

  1. Выбор калькулятора: Пользователь выбирает калькулятор в меню
  2. Загрузка конфигурации: CalculatorEngine получает конфигурацию из реестра
  3. Рендеринг полей: Динамически создаются поля на основе fields из конфигурации
  4. Ввод данных: Пользователь заполняет поля
  5. Расчет: При изменении полей автоматически пересчитываются все шаги, подитоги и дополнительные расчеты
  6. Отправка: Данные отправляются на бэкенд через /api/submit
  7. Telegram: Бэкенд отправляет форматированное сообщение в Telegram

Группировка полей

Поля можно группировать для правильного расположения блоков расчета:

{
  id: 'weight',
  groupName: 'base',        // Группа "base"
  showStepAfter: 'base',   // После группы показать расчет "base"
}
{
  id: 'price',
  groupName: 'base',        // Тот же группа
}
// Блок расчета "Себестоимость основы" появится здесь

Форматирование Telegram сообщений

Каждый калькулятор может иметь функцию formatTelegramMessage:

formatTelegramMessage: (values, steps, subtotals, additional) => {
  let text = `🧼 <b>Расчёт мыла:</b>\n\n`;
  text += `💵 Себестоимость: ${subtotals.total.toFixed(1)}\n`;
  return text;
}

Если функция не указана, используется универсальное форматирование.

API интеграция

Определение URL

Фронтенд автоматически определяет URL API:

const isLocalhost = window.location.hostname === 'localhost';
const apiUrl = isLocalhost
  ? 'http://localhost:3001/api/submit'
  : 'https://api-dosoap.duckdns.org/api/submit';

Формат запроса

FormData {
  chat_id: string;
  calculator_id: string;
  calculator_name: string;
  telegram_message: string;  // Готовое сообщение
  photo?: File;              // Опциональное фото
  // ... остальные поля
}

Добавление нового калькулятора

Шаг 1: Создать модуль

mkdir frontend/calculators/my-calc
touch frontend/calculators/my-calc/config.ts
touch frontend/calculators/my-calc/calc.ts  # опционально

Шаг 2: Создать конфигурацию

См. frontend/docs/calculator-creation-guide.md

Шаг 3: Зарегистрировать

В frontend/lib/calculator-registry.ts:

import { myCalcConfig } from '@/calculators/my-calc/config';
registerCalculator(myCalcConfig);

Окружение разработки

Платформы

  • Разработка: Windows с PowerShell
  • Хостинг: Ubuntu Linux

Особенности разработки на Windows

  • PowerShell не поддерживает оператор && для цепочки команд
  • Используйте ; или выполняйте команды отдельно
  • Пути в Git и конфигах всегда используют /, даже на Windows
  • При работе через SSH используйте Linux команды

Локальная разработка (Windows + PowerShell)

# Frontend - один терминал
cd frontend
npm install
npm run dev

# Backend - отдельный терминал
cd backend
node bot.js

Деплой

Сервер

  • ОС: Ubuntu Linux
  • IP: 192.168.0.19
  • Пользователь: dosai
  • Путь: ~/projects/DoSoapCalc
  • Управление процессами: PM2

Процессы PM2

  • dosoap-frontend - Next.js приложение
  • dosoap-backend - Express сервер

Команды деплоя

С локального Windows (PowerShell):

# Отправить изменения
git push origin dev

# Подключиться и обновить сервер (Ubuntu команды через SSH)
ssh dosai@192.168.0.19 "cd ~/projects/DoSoapCalc && git pull origin dev && cd frontend && npm run build && pm2 restart dosoap-frontend dosoap-backend"

Или на сервере напрямую (Ubuntu):

cd ~/projects/DoSoapCalc
git pull origin dev
cd frontend && npm run build
pm2 restart dosoap-frontend dosoap-backend

Обработка ошибок

Расчеты

Все формулы должны проверять:

  • Деление на ноль → вернуть 0
  • Пустые значения → вернуть 0
  • NaN → вернуть 0

Пример:

if (weight <= 0 || price <= 0) return 0;
return (weight / 1000) * price;

API запросы

try {
  const res = await fetch(apiUrl, { method: 'POST', body: formData });
  if (!res.ok) throw new Error('Server error');
} catch (err) {
  alert('Ошибка сети при отправке расчёта');
}

Известные особенности

  1. Статический экспорт: Next.js собирается в статические файлы, нет серверного рендеринга
  2. Telegram Bot Token: Хранится в переменных окружения на сервере
  3. Chat ID: Передается через URL параметр ?chat_id=... или через Telegram бота
  4. Фото: Отправляются через FormData, обрабатываются multer на бэкенде