DoSoapCalc/CALCULATOR_GUIDE.md

194 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Руководство по добавлению нового калькулятора
Это руководство описывает, как добавить новый калькулятор в систему DoSoapCalc.
## Архитектура
Система использует модульную архитектуру с регистрацией калькуляторов:
- Каждый калькулятор — отдельный модуль с формулой, схемой полей и шаблоном сообщения
- Общие компоненты автоматически генерируют формы и обрабатывают запросы
- Динамическая маршрутизация на основе типа калькулятора
## Шаги добавления нового калькулятора
### 1. Создание модуля калькулятора на Backend
Создайте файл `backend/calculators/[calculator-name].js` (например, `candle.js`).
#### Структура модуля:
```javascript
// calculators/[calculator-name].js
const fieldSchema = [
{ id: 'itemName', name: 'itemName', label: 'Название изделия', type: 'text', required: true },
{ id: 'weight', name: 'weight', label: 'Вес, г', type: 'number', required: true },
// ... другие поля
];
function calculate(data) {
// Ваша формула расчёта
const total = /* вычисления */;
return {
// промежуточные результаты
total: round(total),
};
}
function formatMessage(data, result) {
// Шаблон сообщения для Telegram
let text = `...`;
return text;
}
function getRequiredFields() {
return fieldSchema.filter((f) => f.required).map((f) => f.name);
}
function getNumericFields() {
return fieldSchema.filter((f) => f.type === 'number').map((f) => f.name);
}
module.exports = {
id: 'calculator-name', // уникальный ID
name: 'Название калькулятора',
fieldSchema,
calculate,
formatMessage,
getRequiredFields,
getNumericFields,
};
```
#### Пример поля:
```javascript
{
id: 'fieldId', // уникальный ID поля
name: 'fieldName', // имя поля (используется в данных)
label: 'Название поля', // метка для пользователя
type: 'text' | 'number', // тип поля
required: true | false, // обязательное ли поле
group: 'packaging', // (опционально) группа для группировки полей
}
```
### 2. Регистрация на Backend
Откройте `backend/calculators/index.js` и добавьте калькулятор:
```javascript
const newCalculator = require('./[calculator-name]');
const calculators = {
soap: soapCalculator,
'[calculator-name]': newCalculator, // добавьте здесь
};
```
### 3. Создание модуля калькулятора на Frontend
Создайте файл `frontend/lib/calculators/[calculator-name].ts`.
#### Структура модуля:
```typescript
// lib/calculators/[calculator-name].ts
import type { Calculator, CalculatorField, CalculationResult } from '@/types/calculator';
const fieldSchema: CalculatorField[] = [
{ id: 'itemName', name: 'itemName', label: 'Название изделия', type: 'text', required: true },
// ... другие поля (синхронно с backend!)
];
function calculate(data: Record<string, any>): CalculationResult {
// Та же формула, что и на backend
return {
total: round(total),
};
}
const newCalculator: Calculator = {
id: '[calculator-name]',
name: 'Название калькулятора',
fieldSchema,
calculate,
getRequiredFields: () => fieldSchema.filter((f) => f.required).map((f) => f.name),
getNumericFields: () => fieldSchema.filter((f) => f.type === 'number').map((f) => f.name),
};
export default newCalculator;
```
**Важно:** Схема полей и формула должны совпадать с backend!
### 4. Регистрация на Frontend
Откройте `frontend/lib/calculators/index.ts` и добавьте:
```typescript
import newCalculator from './[calculator-name]';
const calculators: Record<string, Calculator> = {
soap: soapCalculator,
'[calculator-name]': newCalculator, // добавьте здесь
};
```
### 5. Проверка работы
1. Перезапустите backend: `node bot.js`
2. Пересоберите frontend: `npm run build`
3. Откройте в браузере: `/[calculator-name]?chat_id=YOUR_CHAT_ID`
## Примеры
### Простой калькулятор (только базовые поля)
См. файлы:
- `backend/calculators/candle.js` - пример калькулятора свечей
- `frontend/lib/calculators/candle.ts` - frontend версия
### Калькулятор с группированными полями
Для группировки полей используйте параметр `group`:
```javascript
{ id: 'box', name: 'box', label: 'Пакет', type: 'number', group: 'packaging' },
{ id: 'ribbon', name: 'ribbon', label: 'Лента', type: 'number', group: 'packaging' },
```
Поля с одинаковой группой будут автоматически сгруппированы в форме.
## Советы
1. **Синхронизация:** Всегда поддерживайте синхронизацию между backend и frontend схемами
2. **Валидация:** Используйте `required: true` для обязательных полей
3. **Форматирование:** В `formatMessage` используйте HTML для форматирования (поддерживается Telegram)
4. **Округление:** Используйте функцию `round()` для округления результатов
## Структура файлов
```
backend/
├── calculators/
│ ├── index.js # Регистрация калькуляторов
│ ├── soap.js # Пример: калькулятор мыла
│ └── [new-calculator].js # Ваш новый калькулятор
frontend/
├── lib/
│ └── calculators/
│ ├── index.ts # Регистрация калькуляторов
│ ├── soap.ts # Пример: калькулятор мыла
│ └── [new-calculator].ts # Ваш новый калькулятор
```
## Что дальше?
После добавления калькулятора:
1. Протестируйте расчёты вручную
2. Проверьте отправку в Telegram
3. Убедитесь, что валидация работает корректно
4. Добавьте обработку специфичных данных (если нужно)