283 lines
9.6 KiB
Markdown
283 lines
9.6 KiB
Markdown
# База знаний проекта 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
|
||
Определяет поле ввода в калькуляторе:
|
||
```typescript
|
||
{
|
||
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
|
||
Шаг расчета (например, "Себестоимость основы"):
|
||
```typescript
|
||
{
|
||
id: string;
|
||
name: string;
|
||
formula: (values: Record<string, number>) => number;
|
||
formulaDescription?: string;
|
||
}
|
||
```
|
||
|
||
### SubtotalConfig
|
||
Подитог (например, "Итого себестоимость"):
|
||
```typescript
|
||
{
|
||
id: string;
|
||
name: string;
|
||
formula: (values, steps) => number;
|
||
highlight?: boolean; // Выделить визуально
|
||
formulaDescription?: string;
|
||
}
|
||
```
|
||
|
||
### AdditionalCalculation
|
||
Дополнительный расчет (например, "Цена за 100г"):
|
||
```typescript
|
||
{
|
||
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
|
||
|
||
## Группировка полей
|
||
|
||
Поля можно группировать для правильного расположения блоков расчета:
|
||
|
||
```typescript
|
||
{
|
||
id: 'weight',
|
||
groupName: 'base', // Группа "base"
|
||
showStepAfter: 'base', // После группы показать расчет "base"
|
||
}
|
||
{
|
||
id: 'price',
|
||
groupName: 'base', // Тот же группа
|
||
}
|
||
// Блок расчета "Себестоимость основы" появится здесь
|
||
```
|
||
|
||
## Форматирование Telegram сообщений
|
||
|
||
Каждый калькулятор может иметь функцию `formatTelegramMessage`:
|
||
|
||
```typescript
|
||
formatTelegramMessage: (values, steps, subtotals, additional) => {
|
||
let text = `🧼 <b>Расчёт мыла:</b>\n\n`;
|
||
text += `💵 Себестоимость: ${subtotals.total.toFixed(1)} ₽\n`;
|
||
return text;
|
||
}
|
||
```
|
||
|
||
Если функция не указана, используется универсальное форматирование.
|
||
|
||
## API интеграция
|
||
|
||
### Определение URL
|
||
|
||
Фронтенд автоматически определяет URL API:
|
||
```typescript
|
||
const isLocalhost = window.location.hostname === 'localhost';
|
||
const apiUrl = isLocalhost
|
||
? 'http://localhost:3001/api/submit'
|
||
: 'https://api-dosoap.duckdns.org/api/submit';
|
||
```
|
||
|
||
### Формат запроса
|
||
|
||
```typescript
|
||
FormData {
|
||
chat_id: string;
|
||
calculator_id: string;
|
||
calculator_name: string;
|
||
telegram_message: string; // Готовое сообщение
|
||
photo?: File; // Опциональное фото
|
||
// ... остальные поля
|
||
}
|
||
```
|
||
|
||
## Добавление нового калькулятора
|
||
|
||
### Шаг 1: Создать модуль
|
||
```bash
|
||
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`:
|
||
```typescript
|
||
import { myCalcConfig } from '@/calculators/my-calc/config';
|
||
registerCalculator(myCalcConfig);
|
||
```
|
||
|
||
## Окружение разработки
|
||
|
||
### Платформы
|
||
- **Разработка**: Windows с PowerShell
|
||
- **Хостинг**: Ubuntu Linux
|
||
|
||
### Особенности разработки на Windows
|
||
- PowerShell не поддерживает оператор `&&` для цепочки команд
|
||
- Используйте `;` или выполняйте команды отдельно
|
||
- Пути в Git и конфигах всегда используют `/`, даже на Windows
|
||
- При работе через SSH используйте Linux команды
|
||
|
||
### Локальная разработка (Windows + PowerShell)
|
||
```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):**
|
||
```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):**
|
||
```bash
|
||
cd ~/projects/DoSoapCalc
|
||
git pull origin dev
|
||
cd frontend && npm run build
|
||
pm2 restart dosoap-frontend dosoap-backend
|
||
```
|
||
|
||
## Обработка ошибок
|
||
|
||
### Расчеты
|
||
Все формулы должны проверять:
|
||
- Деление на ноль → вернуть 0
|
||
- Пустые значения → вернуть 0
|
||
- NaN → вернуть 0
|
||
|
||
Пример:
|
||
```typescript
|
||
if (weight <= 0 || price <= 0) return 0;
|
||
return (weight / 1000) * price;
|
||
```
|
||
|
||
### API запросы
|
||
```typescript
|
||
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 на бэкенде
|
||
|